#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.

Reply via email to