Django form fields

A pointer on how to process them.

Django's form generation machinery for the most part is fine and straightforward, but on a recent project I ran into problems with a form that accepted files. The documentation is all there, but changes in how things work and an emphasis on forms for models make things harder to understand than they should be.

First, lets look at the form:

class MyForm(forms.Form):
   myfile = forms.FileField() # ...

and the original code for handling it:

def show_form (cls, request):
   # instantiate form in one of several ways ...
   form_cls = cls.MyForm
   # if the form has been submitted ...
   if request.method == 'POST':
      form = form_cls(request.POST)
   # if the form is valid
   if form.is_valid():
      # get the clean data and do the work
      cls.process_form (form.cleaned_data)
   else:
      # if you're coming to the form anew, make an unbound form
      form = form_cls()
      render_to_response('myform.html', {'form': form })

When the form is instantiated, it looks fine. But when it is submitted, the validation always fails on the file field, saying the file is required, whether or not a file has been selected in the form.

Strange. The field is, by default, required so a file needed but is not being detected. By tracking the validation, we can see that it is working correctly.

The answer is that files are now stored in the request apart from the rest of the data in request.FILES. This has to be passed to the form c'tor:

if request.method == 'POST':
   form = form_cls(request.POST, request.FILES)

at which point the validation passes. After validation the file can be found in the clean data as an UploadedFile object.