Skip to content

Instantly share code, notes, and snippets.

@akaihola
Created February 17, 2010 15:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akaihola/306689 to your computer and use it in GitHub Desktop.
Save akaihola/306689 to your computer and use it in GitHub Desktop.
from django.core import validators
from django.forms import MultiValueField
from django.forms.util import ErrorList
from django.core.exceptions import ValidationError
class ProperMultiValueField(MultiValueField):
"""django.forms.fields.MultiValueField with a validation fix
If a MultiValueField is ``required=True``, it should still be
valid even if one or more of the sub-fields are empty. In Django
(from newforms-admin until at least 1.1) this is not the case: any
empty sub-field causes a validation error for the whole
multi-value field. This class fixes this behavior.
To get the Django stock MultiValueField behavior with this class,
declare all sub-fields as ``required=True``.
"""
def clean(self, value):
"""
Validates every value in the given list. A value is validated against
the corresponding Field in self.fields.
For example, if this MultiValueField was instantiated with
fields=(DateField(), TimeField()), clean() would call
DateField.clean(value[0]) and TimeField.clean(value[1]).
"""
clean_data = []
errors = ErrorList()
if not value or isinstance(value, (list, tuple)):
if not value or not [v for v in value if v not in validators.EMPTY_VALUES]:
if self.required:
raise ValidationError(self.error_messages['required'])
else:
return self.compress([])
else:
raise ValidationError(self.error_messages['invalid'])
for i, field in enumerate(self.fields):
try:
field_value = value[i]
except IndexError:
field_value = None
# The only change to MultiValueField is here:
# ``self.required`` was changed to ``field.required``
if field.required and field_value in validators.EMPTY_VALUES:
raise ValidationError(self.error_messages['required'])
try:
clean_data.append(field.clean(field_value))
except ValidationError, e:
errors.extend(e.messages)
if errors:
raise ValidationError(errors)
out = self.compress(clean_data)
self.validate(out)
return out
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment