title: Django forms.FileField(required=True) is passing validation if empty
body: <p>I have a Django Form (not a ModelForm) with a required FileField.  According to <a href="https://docs.djangoproject.com/en/1.3/ref/forms/fields/#filefield" rel="noreferrer">the FileField documentation</a>, validation of the FileField should validate that non-empty file data has been bound to the form, but I am not seeing this behavior.  Instead I am able to submit the form without a file and the form passes validation.  The expected behavior would be to fail validation.</p>
  
  <p>Things work as expected when a file is specified in the form.</p>
  
  <p>My form looks something like this:</p>
  
  <pre><code>class BucketUploadForm(forms.Form):
    file = forms.FileField(required=True)  # required=True is the default, but I'm being explicit
  
    def clean(self):
      upload_to = '/some/path'
      upload_to += self.cleaned_data['file'].name  # this is raising a KeyError
  </code></pre>
  
  <p>My view looks something like this:</p>
  
  <pre><code>def bucket_upload(request):
    if request.method == 'POST':
      form = BucketUploadForm(request.POST, request.FILES)
      if form.is_valid():  # this is raising the aforementioned KeyError when no file is submitted
        do_stuff()
        return HttpResponseRedirect(some_url)
      else:
        form = BucketUploadForm(initial=request.GET)
      return render_to_response('handin/bucket_upload.html', {'form': form}, context_instance=RequestContext(request))
  </code></pre>
  
  <p>My template looks something like this:</p>
  
  <pre><code>&lt;form action="" method="post" enctype="multipart/form-data"&gt;
  {% csrf_token %}
  &lt;table&gt;
  {{ form }}
  &lt;/table&gt;
  &lt;input type="submit" value="Upload" /&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>The traceback looks like this:</p>
  
  <pre><code>Django Version: 1.3.1
  Python Version: 2.7.3
  Installed Applications:
  ['django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.sites',
   'django.contrib.messages',
   'django.contrib.staticfiles',
   'django.contrib.admin',
   'django.contrib.admindocs',
   'hgrepo',
   'sshkey',
   'handin',
   'accounts']
  Installed Middleware:
  ('django.middleware.common.CommonMiddleware',
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.csrf.CsrfViewMiddleware',
   'django.contrib.auth.middleware.AuthenticationMiddleware',
   'django.contrib.messages.middleware.MessageMiddleware')
  
  
  Traceback:
  File "/usr/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
    111.                         response = callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python2.7/dist-packages/django/contrib/auth/decorators.py" in _wrapped_view
    23.                 return view_func(request, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/django/views/decorators/http.py" in inner
    45.             return func(request, *args, **kwargs)
  File "/home/sduckwo/projects/webhandin/webhandin/handin/views.py" in bucket_upload
    461.     if form.is_valid():
  File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in is_valid
    121.         return self.is_bound and not bool(self.errors)
  File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in _get_errors
    112.             self.full_clean()
  File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in full_clean
    268.         self._clean_form()
  File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in _clean_form
    296.             self.cleaned_data = self.clean()
  File "/home/sduckwo/projects/webhandin/webhandin/handin/forms.py" in clean
    116.       upload_to += self.cleaned_data['file'].name
  
  Exception Type: KeyError at /courses/a/b/assignments/c/sduckwo/upload
  Exception Value: 'file'
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Removing the clean method from BucketUploadForm causes the FileField's validation to fail as expected.  However, I need the clean method for other checks, so removing it permanently is not an option.</p>
  
  <p>I've also found that by modifying the clean method to look like this:</p>
  
  <pre><code>class BucketUploadForm(forms.Form):
    file = forms.FileField(required=True)  # required=True is the default, but I'm being explicit
  
    def clean(self):
      if 'file' not in self.cleaned_data:
        raise ValidationError('No file or empty file given')
      upload_to = '/some/path'
      upload_to += self.cleaned_data['file'].name  # this is raising a KeyError
  </code></pre>
  
  <p>then validation fails as expected, but I get two error messages:</p>
  
  <ol>
  <li>'No file or empty file given', raised by BucketUploadForm.clean()</li>
  <li>'This field is required', raised by FileField.clean(), which is what I was after in the first place.</li>
  </ol>
  
  <p>This tells me that FileField.clean() is raising a ValidationError, but that exception is somehow being ignored unless BucketUploadForm.clean() either does not exist or also raises a ValidationError.</p>
  
  <p>So now I'm maybe a little closer to my end goal but still very confused.</p>