Ticket #5335: form_error_append_r16741.diff

File form_error_append_r16741.diff, 5.5 KB (added by vbmendes, 4 years ago)

Reviewed patch with unittests

  • docs/ref/forms/validation.txt

     
    137137display itself in different ways. So you can treat ``_errors`` as a dictionary
    138138mapping field names to lists.
    139139
    140 If you want to add a new error to a particular field, you should check whether
    141 the key already exists in ``self._errors`` or not. If not, create a new entry
    142 for the given key, holding an empty ``ErrorList`` instance. In either case,
    143 you can then append your error message to the list for the field name in
    144 question and it will be displayed when the form is displayed.
     140If you want to add a new error to a particular field, you can append your error
     141message to the list for the field name in question by using ``append()``.
     142Django will check if the key already exists, otherwise it will create an empty
     143``ErrorList`` instance. Then the error message will be displayed when the form
     144is displayed.
    145145
    146146There is an example of modifying ``self._errors`` in the following section.
    147147
     
    337337                # We know these are not in self._errors now (see discussion
    338338                # below).
    339339                msg = u"Must put 'help' in subject when cc'ing yourself."
    340                 self._errors["cc_myself"] = self.error_class([msg])
    341                 self._errors["subject"] = self.error_class([msg])
     340                self._errors["cc_myself"].append(msg)
     341                self._errors["subject"].append(msg)
    342342
    343343                # These fields are no longer valid. Remove them from the
    344344                # cleaned data.
     
    350350
    351351As you can see, this approach requires a bit more effort, not withstanding the
    352352extra design effort to create a sensible form display. The details are worth
    353 noting, however. Firstly, earlier we mentioned that you might need to check if
    354 the field name keys already exist in the ``_errors`` dictionary. In this case,
    355 since we know the fields exist in ``self.cleaned_data``, they must have been
    356 valid when cleaned as individual fields, so there will be no corresponding
    357 entries in ``_errors``.
     353noting, however. Firstly, we mentioned that in order to add errors to the
     354fields, you just need to ``append()`` your error message in the ``_errors``
     355dictionary.
    358356
    359357Secondly, once we have decided that the combined data in the two fields we are
    360358considering aren't valid, we must remember to remove them from the
  • tests/regressiontests/forms/tests/util.py

     
    11# -*- coding: utf-8 -*-
    22from django.core.exceptions import ValidationError
     3from django import forms
    34from django.forms.util import *
    45from django.utils.translation import ugettext_lazy
    56from django.utils.unittest import TestCase
     
    5960                         '<ul class="errorlist"><li>nameExample of link: &lt;a href=&quot;http://www.example.com/&quot;&gt;example&lt;/a&gt;</li></ul>')
    6061        self.assertEqual(str(ErrorDict({'name': mark_safe(example)})),
    6162                         '<ul class="errorlist"><li>nameExample of link: <a href="http://www.example.com/">example</a></li></ul>')
     63
     64
     65class AppendingFieldErrorMessagesTestCase(TestCase):
     66
     67    def test_errors_messages_can_be_appended_to_fields_error_list(self):
     68        error_msg = "Field1 can't be greather than field2."
     69        class TestForm(forms.Form):
     70            field1 = forms.IntegerField()
     71            field2 = forms.IntegerField()
     72
     73            def clean(self):
     74                if self.cleaned_data['field1'] > self.cleaned_data['field2']:
     75                    self._errors['field1'].append(error_msg)
     76
     77        form = TestForm({'field1': 3, 'field2': 2})
     78        form.is_valid()
     79        self.assertEqual(form.errors['field1'], [error_msg])
     80        self.assertEqual(form.errors['field2'], [])
     81
     82    def test_appending_error_messages_to_fields_errors_list_dont_overwrite_other_messages(self):
     83        class TestForm(forms.Form):
     84            password = forms.CharField()
     85            confirm_password = forms.CharField()
     86
     87            def clean_password(self):
     88                value = self.cleaned_data['password']
     89                if len(value) < 6:
     90                    raise forms.ValidationError("Password must be longer than 6 characters.")
     91                return value
     92
     93            def clean(self):
     94                if self.cleaned_data.get('password') != self.cleaned_data.get('confirm_password'):
     95                    self._errors['password'].append("Passwords don't match.")
     96
     97        form = TestForm({'password': 'small', 'confirm_password': 'smal'})
     98        form.is_valid()
     99        self.assertEqual(form.errors['password'], ["Password must be longer than 6 characters.", "Passwords don't match."])
     100        self.assertEqual(form.errors['confirm_password'], [])
     101
  • django/forms/util.py

     
    3333    def as_text(self):
    3434        return u'\n'.join([u'* %s\n%s' % (k, u'\n'.join([u'  * %s' % force_unicode(i) for i in v])) for k, v in self.items()])
    3535
     36    def __getitem__(self, field):
     37        return self.setdefault(field, ErrorList())
     38
    3639class ErrorList(list, StrAndUnicode):
    3740    """
    3841    A collection of errors that knows how to display itself in various formats.
Back to Top