views:

416

answers:

3

I've been doing things like this in the clean method:

if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      raise forms.ValidationError('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
      raise forms.ValidationError('The start date cannot be later than the end date.')

But then that means that the form can only raise one of these errors at a time. Is there a way for the form to raise both of these errors?

EDIT #1: Any solutions for the above are great, but would love something that would also work in a scenario like:

if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      raise forms.ValidationError('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
      raise forms.ValidationError('The start date cannot be later than the end date.')
super(FooAddForm, self).clean()

Where FooAddForm is a ModelForm and has unique constraints that might also cause errors. If anyone knows of something like that, that would be great...

+4  A: 
errors = []
if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      errors.append('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
     errors.append('The start date cannot be later than the end date.')

if errors:
    raise forms.ValidationError(errors)
Daniel Roseman
Grrr.... was trying to give this +1, but I accidently clicked twice and it now says "vote too old to be changed" grrr... Anyway, nice answer :) but I'm still having one problem with it... I've got one clean method on a ModelForm, where it's important to check for unique constraints, but if I do:if errors: raise forms.ValidationError(errors) super(CompetitionAddForm, self).clean() then it's either my errors or the unique constraint errors :-/
Monika Sulik
+3  A: 

http://docs.djangoproject.com/en/1.1/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other

from django.forms.util import ErrorList

def clean(self):

  if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
    msg = 'The type and organization do not match.'
    self._errors['type'] = ErrorList([msg])
    del self.cleaned_data['type']

  if self.cleaned_data['start'] > self.cleaned_data['end']:
    msg = 'The start date cannot be later than the end date.'
    self._errors['start'] = ErrorList([msg])
    del self.cleaned_data['start']

  return self.cleaned_data
kemar
This works very nicely (I wasn't sure if I liked that the error messages were attached to the fields rather than the whole form, but it actually sort of makes more sense this way) and the ModelForm unique constraints work too. So I'm accepting this one - thanks! :)
Monika Sulik
A: 

If you'd prefer that the error messages be attached to the form rather than to specific fields, you can use the key "__all__" like this:

msg = 'The type and organization do not match.'
self._errors['__all__'] = ErrorList([msg])

Also, as the Django docs explain: "if you want to add a new error to a particular field, you should check whether the key already exists in self._errors or not. If not, create a new entry for the given key, holding an empty ErrorList instance. In either case, you can then append your error message to the list for the field name in question and it will be displayed when the form is displayed."

rory