0

Ive been Playing around with django to create an asset management app and have hit a wall on the file upload to model instance behaviour. I am attempting to use the ModelForm class in Forms.py

Basically im pretty certain that form.save() is not writing my uploaded file to disk to update my model instance. Do I have to write a form.save definition into my AssetForm ? or have I missed something else.

Appreciate any help.

My project is built around the Polls tutorial https://docs.djangoproject.com/en/1.8/intro/tutorial01/ and the minimal file upload tutorial at Need a minimal Django file upload example.

Here is my model .py

class Category(models.Model):
    category_text = models.CharField(max_length=200)
    def __str__(self):              # __unicode__ on Python 2
        return self.category_text

class Asset(models.Model):
    asset_text = models.CharField(max_length=200)
    asset_tag = models.CharField(max_length=200)
    asset_category = models.ForeignKey(Category)
    cert_date = models.DateTimeField('cert published')

    def __str__(self):              # __unicode__ on Python 2
        return self.asset_text
    def was_certed_recently(self):
        return self.cert_date >= timezone.now() - datetime.timedelta(days=365)
    was_certed_recently.admin_order_field = 'cert_date'
    was_certed_recently.boolean = True
    was_certed_recently.short_description = 'Certified recently?'
    docfile = models.FileField(upload_to='documents')

Here is my forms.py

from django import forms
from django.forms import ModelForm
from polls.models import Asset





class AssetForm(ModelForm):
    class Meta:
        model = Asset
        fields = '__all__' 

Here is my views.py

# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.http import HttpResponse
#from django.template import RequestContext, loader
from django.shortcuts import get_object_or_404, render
from django.http import Http404 
from polls.models import Asset 
from polls.forms import AssetForm 

def list(request, asset_id):
    # Handle file upload
    ID = asset_id
    p = get_object_or_404(Asset, pk = asset_id)

    if request.method == 'POST':
        form = AssetForm(request.POST, request.FILES, instance= p )
        if form.is_valid():
            form.save()
            # Redirect to the document list after POST
            return HttpResponseRedirect(reverse('list', args=(p.id,)))

    else:
        form = AssetForm() # A empty, unbound form

    # Load documents for the list page
    documents = p



    # Render list page with the documents and the form
    return render_to_response(
        'polls/list.html', 
        {'documents': documents, 'ID': ID, 'form': form},
        context_instance=RequestContext(request )
    )



def index(request):
    latest_asset_list = Asset.objects.order_by('-cert_date')[:]
    context = {'latest_asset_list': latest_asset_list}
    return render(request, 'polls/index.html', context)

url.py

from django.conf.urls import  url
from . import views


urlpatterns = [
    #url(r'^/list/$', 'list', name='list'),
    url(r'^$', views.index, name='index'),
    # ex: /polls/5/
    url(r'^(?P<asset_id>[0-9]+)/$', views.list, name='list'),
    # ex: /polls/5/results/
    url(r'^(?P<asset_id>[0-9]+)/results/$', views.results, name='results'),
    # ex: /polls/5/vote/
    url(r'^(?P<asset_id>[0-9]+)/vote/$', views.vote, name='vote'),

]    

Finally my list.html template

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Minimal Django File Upload Example</title>   
    </head>
    <body>
    <!-- List of uploaded documents -->
    {% if documents %}
        <ul>
            <p>Current Doc.</p>
            <li><a href="{{ documents.docfile.url }}">{{ documents.docfile.name }}</a></li>

        </ul>
    {% else %}
        <p>No documents.</p>
    {% endif %}

    <ul>



 {{ ID }} 



        <!-- Upload form. Note enctype attribute! -->
        <form action="{% url 'list' ID %}" method="post" enctype="multipart/form-data">


            {% csrf_token %}
            <p>{{ form.non_field_errors }}</p>
            <p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
            <p>
                {{ form.docfile.errors }}
                {{ form.docfile }}
            </p>
            <p><input type="submit" value="Upload" /></p>
        </form>
    </body>
</html>  
Community
  • 1
  • 1
user276537
  • 11
  • 3

1 Answers1

0

You're doing various things twice. For example, at the start of your function, you get an Asset into p and then you get the same one into a. Why?

More significantly, in the is_valid() block you create a new Asset object just from the uploaded file, with no other data from the form, but then you save the form itself which should update the existing Asset. This might be the cause of your problem - you should remove the lines with docfile and just save the form.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Thanks for the help Daniel.I have removed the redundant assignments in the views.py code above and removed the lines with docfile from the if form.is_valid() block as u suggested. The form.save() command still fails to write the new file assignment to disk however. – user276537 May 26 '15 at 14:21