Django forms.FileField(required=True) is passing validation if empty -


i have django form (not modelform) required filefield. according the filefield documentation, validation of filefield should validate non-empty file data has been bound form, not seeing behavior. instead able submit form without file , form passes validation. expected behavior fail validation.

things work expected when file specified in form.

my form looks this:

class bucketuploadform(forms.form):   file = forms.filefield(required=true)  # required=true default, i'm being explicit    def clean(self):     upload_to = '/some/path'     upload_to += self.cleaned_data['file'].name  # raising keyerror 

my view looks this:

def bucket_upload(request):   if request.method == 'post':     form = bucketuploadform(request.post, request.files)     if form.is_valid():  # raising aforementioned keyerror when no file 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)) 

my template looks this:

<form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} <table> {{ form }} </table> <input type="submit" value="upload" /> </form> 

the traceback looks this:

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 , 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 @ /courses/a/b/assignments/c/sduckwo/upload exception value: 'file' 

update

removing clean method bucketuploadform causes filefield's validation fail expected. however, need clean method other checks, removing permanently not option.

i've found modifying clean method this:

class bucketuploadform(forms.form):   file = forms.filefield(required=true)  # required=true default, 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  # raising keyerror 

then validation fails expected, 2 error messages:

  1. 'no file or empty file given', raised bucketuploadform.clean()
  2. 'this field required', raised filefield.clean(), after in first place.

this tells me filefield.clean() raising validationerror, exception somehow being ignored unless bucketuploadform.clean() either not exist or raises validationerror.

so i'm maybe little closer end goal still confused.

i think i've seen before. anecdotal experience seems django not stop validation if field missing (e.g. call clean() if missing required fields). says required field missing not including field name in cleaned_data.

scott pointed out documented here:

for field, if field.clean() method raises validationerror, field-specific cleaning method not called. however, cleaning methods remaining fields still executed.

therefore, think solution program clean() method defensively checking if 'file' key in cleaned_data , if isn't, return cleaned_data is. django knows required field missing, is_valid() fail , no harm come.

def clean(self):   upload_to = '/some/path'   if not 'file' in self.cleaned_data:     return self.cleaned_data   upload_to += self.cleaned_data['file'].name 

Comments