#24988: ValidationError fails to set code
---------------------------------+-----------------------------
Reporter: michaeljohnbarr | Owner: nobody
Type: Bug | Status: new
Component: Core (Other) | Version: 1.8
Severity: Normal | Keywords: ValidationError
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------
Assuming the following model:
{{{
class DateRange(models.Model):
start = models.DateField()
end = models.DateField
def clean(self):
super(DateRange, self).clean()
if self.start and self.end:
if self.start >= self.end:
raise ValidationError(
message={
'start': _(
'{start} must come before {end}.'.format(
start=self._meta.get_field(
'start'
).verbose_name,
end=self._meta.get_field(
'end'
).verbose_name,
)
),
'end': _(
'{end} must come after {start}.'.format(
end=self._meta.get_field(
'end'
).verbose_name,
start=self._meta.get_field(
'start'
).verbose_name,
)
),
},
code='invalid',
)
}}}
After then validating the model with a ModelForm, the `code` fails to be
set to `'invalid'` but is instead an empty string. I discovered this when
I was programming tests:
{{{
def test_start_before_end_validation(self):
"""An employee is not allowed to be their own manager."""
TestForm = modelform_factory(
model=DateRange,
fields=('start', 'end')
)
form = TestForm(
data=dict(
start=date(2015, 1, 1),
end=date(1900, 12, 31) # WHOOPS!
)
)
self.assertEqual(first=form.is_valid(), second=False)
# The below fails because the code is '' - we have to leave off
the code
self.assertTrue(form.has_error(field='start'), code='invalid')
self.assertTrue(form.has_error(field='end'), code='invalid')
}}}
Upon inspection of the the `ValidationError` code, I discovered that that
any `ValidationError` that is raised with a type of `dict` or a `list` as
the `message` will never set the code:
{{{
if isinstance(message, dict):
self.error_dict = {}
for field, messages in message.items():
if not isinstance(messages, ValidationError):
messages = ValidationError(messages)
self.error_dict[field] = messages.error_list
elif isinstance(message, list):
self.error_list = []
for message in message:
# Normalize plain strings to instances of ValidationError.
if not isinstance(message, ValidationError):
message = ValidationError(message)
if hasattr(message, 'error_dict'):
self.error_list.extend(sum(message.error_dict.values(), []))
else:
self.error_list.extend(message.error_list)
}}}
According to the
[https://docs.djangoproject.com/en/1.8/ref/forms/validation/#raising-
validationerror documentation on raising ValidationError], it is suggested
to "Provide a descriptive error code to the constructor." Is this a bug?
I believe the "fix" would be as simple as to pass `code=code` following
the message/messages, but I may be wrong. Thoughts?
--
Ticket URL: <https://code.djangoproject.com/ticket/24988>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/058.60c4a65e35bd3977473b031c89f5d144%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.