Validating File Uploads with Django 1.0 (updated)

| | Comments () | TrackBacks (0)

A long time ago, I wrote a blog post and some code that validates file uploads in Django. In the last week, it seems a lot of people have been interested in the post and since Django finally has a stable 1.0 release, I thought I would update the previous blog post.

Custom field, with validation

First, here is the new code for a Django form field that validates the filename and content type of an uploaded file. This example makes sure that the file is a Word, OpenOffice, text, HTML or PDF document:

# v_fields.py
from django import forms
from django.utils.translation import gettext as _

class DocumentValidationError(forms.ValidationError):
    def __init__(self):
        super(DocumentValidationError, self).__init__(_(u'Document types accepted: ') + ', '.join(DocumentField.valid_file_extensions))

class DocumentField(forms.FileField):
    """A validating document upload field"""
    valid_content_types = ('text/html', 'text/plain', 'text/rtf',
                           'text/xml', 'application/msword',
                           'application/rtf', 'application/pdf')
    valid_file_extensions = ('odt', 'pdf', 'doc', 'txt',
                             'html', 'rtf', 'htm', 'xhtml')

    def __init__(self, *args, **kwargs):
        super(DocumentField, self).__init__(*args, **kwargs)

    def clean(self, data, initial=None):
        f = super(DocumentField, self).clean(data, initial)
        ext = splitext(f.name)[1][1:].lower()
        if ext in DocumentField.valid_file_extensions \
           and data['content-type'] in DocumentField.valid_content_types:
            return f
        raise DocumentValidationError()

Warning, this is only the form field. Second, You will have to do some extra wiring to be able to display it. Before I show you how to hook it up, we need a sample model. The following is a Document model that has a title, a content_type and a document field:

# models.py
from django.db import models
from django.utils.translation import gettext as _

class Document(models.Model):
    content_type = models.CharField(max_length=5, blank=True, null=True)
    document = models.FileField(upload_to='documents/%Y/')
    title = models.CharField(_(u'Title'), max_length=80)

Custom form

I'm using a FileField for the document field. Next, we have the wiring for a form:

# v_forms.py
from models import Document
from django.forms import ModelForm

from v_fields import DocumentField

class DocumentForm(ModelForm):
    document = DocumentField()
    class Meta:
        model = Document
        fields = ('title', 'document')

Whenever a form is created for the Document model, the document field will be a DocumentField object. This is the field that has the validation method as shown above.

Custom admin form

Third, lovely Django finally allows us to create and use custom forms with the admin module and so I wrote a bit of code that hooks into the above form.

# admin.py
from django.contrib import admin
from django_sample.documents.models import Document

from v_forms import DocumentForm

class DocumentAdmin(admin.ModelAdmin):
    form = DocumentForm

admin.site.register(Document, DocumentAdmin)

More information

You can look up more information on each component:

Leave some feedback! Does it work for you? How could I improve it?

0 TrackBacks

Listed below are links to blogs that reference this entry: Validating File Uploads with Django 1.0 (updated).

TrackBack URL for this entry: http://www.neverfriday.com/cgi-bin/mt/mt-tb.cgi/22

Comments

About this Entry

This page contains a single entry by Rudolf Olah published on September 9, 2008 5:24 PM.

Emacs: Org-mode WikiPedia links was the previous entry in this blog.

JavaScript, jQuery and DNA is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Jobs

Powered by Movable Type 4.1