Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

File Upload Django simple example

Project tree

A basic Django 1.3 project with single app and media/ directory for uploads.
minimal-django-file-upload-example/
src
/
myproject
/
database
/
sqlite
.db
media
/
myapp
/
templates
/
myapp
/
list
.html
forms
.py
models
.py
urls
.py
views
.py
__init__
.py
manage
.py
settings
.py
urls
.py

1. Settings: myproject/settings.py


To upload and serve files, you need to specify where Django stores uploaded files and from what URL Django serves them. MEDIA_ROOT and MEDIA_URL are in settings.py by default but they are empty. See the first lines in Django Managing Files for details. Remember also set the database and add myapp to INSTALLED_APPS
...
DATABASES
= {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': '/path/to/myproject/database/sqlite.db'),
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
...
MEDIA_ROOT
= '/path/to/myproject/media/'
MEDIA_URL
= '/media/'
...
INSTALLED_APPS
= (
...
'myapp',
)

2. Model: myproject/myapp/models.py

Next you need a model with a FileField. This particular field stores files e.g. to media/documents/2011/12/24/ based on current date and MEDIA_ROOT. See FileField reference.
# -*- coding: utf-8 -*-
from django.db import models

class Document(models.Model):
docfile
= models.FileField(upload_to='documents/%Y/%m/%d')

3. Form: myproject/myapp/forms.py

To handle upload nicely, you need a form. This form has only one field but that is enough. See Form FileField reference for details.
# -*- coding: utf-8 -*-
from django import forms

class DocumentForm(forms.Form):
docfile
= forms.FileField(
label
='Select a file',
help_text
='max. 42 megabytes'
)

4. View: myproject/myapp/views.py

A view where all the magic happens. Pay attention how request.FILES are handled. For me, it was really hard to spot the fact that request.FILES['docfile'] can be saved to models.FileField just like that. The model's save() handles the storing of the file to the filesystem automatically.
# -*- 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 myproject.myapp.models import Document
from myproject.myapp.forms import DocumentForm

def list(request):
# Handle file upload
if request.method == 'POST':
form
= DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc
= Document(docfile = request.FILES['docfile'])
newdoc
.save()

# Redirect to the document list after POST
return HttpResponseRedirect(reverse('myapp.views.list'))
else:
form
= DocumentForm() # A empty, unbound form

# Load documents for the list page
documents
= Document.objects.all()

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

5. Project URLs: myproject/urls.py

Django does not serve MEDIA_ROOT by default. That would be dangerous in production environment. But in developement stage, we could cut short. Pay attention to the last line. That line enables Django to serve files from MEDIA_URL. This works only in developement stage.
See django.conf.urls.static.static reference for details. See also this discussion about serving media files.
# -*- coding: utf-8 -*-
from django.conf.urls.defaults import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static

urlpatterns
= patterns('',
(r'^', include('myapp.urls')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

6. App URLs: myproject/myapp/urls.py

To make the view accessible, you must specify urls for it. Nothing special here.
# -*- coding: utf-8 -*-
from django.conf.urls.defaults import patterns, url

urlpatterns
= patterns('myapp.views',
url
(r'^list/$', 'list', name='list'),
)

7. Template: myproject/myapp/templates/myapp/list.html

The last part: template for the list and the upload form below it. The form must have enctype-attribute set to "multipart/form-data" and method set to "post" to make upload to Django possible. See File Uploads documentation for details.
The FileField has many attributes that can be used in templates. E.g. {{ document.docfile.url }} and {{ document.docfile.name }} as in the template. See more about these in Using files in models article andThe File object documentation.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Minimal Django File Upload Example</title>
</head>
<body>
<!-- List of uploaded documents -->
{% if documents %}
<ul>
{% for document in documents %}
<li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}

<!-- Upload form. Note enctype attribute! -->
<form action="{% url list %}" 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>

8. Initialize

Just run syncdb and runserver.
> cd myproject
> python manage.py syncdb
> python manage.py runserver

Results

Finally, everything is ready. On default Django developement environment the list of uploaded documents can be seen at localhost:8000/list/. Today the files are uploaded to /path/to/myproject/media/documents/2011/12/17/ and can be opened from the list.
I hope this answer will help someone as much as it would have helped me.



Source


This post first appeared on Makingiants, please read the originial post: here

Share the post

File Upload Django simple example

×

Subscribe to Makingiants

Get updates delivered right to your inbox!

Thank you for your subscription

×