Loading django/forms/forms.py +9 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,15 @@ class BaseForm(object): if field in self.cleaned_data: del self.cleaned_data[field] def has_error(self, field, code=None): if code is None: return field in self.errors if field in self.errors: for error in self.errors.as_data()[field]: if error.code == code: return True return False def full_clean(self): """ Cleans all of self.data and populates self._errors and Loading docs/ref/forms/api.txt +11 −0 Original line number Diff line number Diff line Loading @@ -182,6 +182,17 @@ when defining form errors. Note that ``Form.add_error()`` automatically removes the relevant field from ``cleaned_data``. .. method:: Form.has_error(field, code=None) .. versionadded:: 1.8 This method returns a boolean designating whether a field has an error with a specific error ``code``. If ``code`` is ``None``, it will return ``True`` if the field contains any errors at all. To check for non-field errors use :data:`~django.core.exceptions.NON_FIELD_ERRORS` as the ``field`` parameter. Behavior of unbound forms ~~~~~~~~~~~~~~~~~~~~~~~~~ Loading docs/releases/1.8.txt +3 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,9 @@ Forms * Form widgets now render attributes with a value of ``True`` or ``False`` as HTML5 boolean attributes. * The new :meth:`~django.forms.Form.has_error()` method allows checking if a specific error has happened. Internationalization ^^^^^^^^^^^^^^^^^^^^ Loading tests/forms_tests/tests/test_forms.py +34 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import datetime import json import warnings from django.core.exceptions import NON_FIELD_ERRORS from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import RegexValidator from django.forms import ( Loading Loading @@ -739,6 +740,39 @@ class FormsTestCase(TestCase): with six.assertRaisesRegex(self, ValueError, "has no field named"): f.add_error('missing_field', 'Some error.') def test_has_error(self): class UserRegistration(Form): username = CharField(max_length=10) password1 = CharField(widget=PasswordInput, min_length=5) password2 = CharField(widget=PasswordInput) def clean(self): if (self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']): raise ValidationError( 'Please make sure your passwords match.', code='password_mismatch', ) f = UserRegistration(data={}) self.assertTrue(f.has_error('password1')) self.assertTrue(f.has_error('password1', 'required')) self.assertFalse(f.has_error('password1', 'anything')) f = UserRegistration(data={'password1': 'Hi', 'password2': 'Hi'}) self.assertTrue(f.has_error('password1')) self.assertTrue(f.has_error('password1', 'min_length')) self.assertFalse(f.has_error('password1', 'anything')) self.assertFalse(f.has_error('password2')) self.assertFalse(f.has_error('password2', 'anything')) f = UserRegistration(data={'password1': 'Bonjour', 'password2': 'Hello'}) self.assertFalse(f.has_error('password1')) self.assertFalse(f.has_error('password1', 'required')) self.assertTrue(f.has_error(NON_FIELD_ERRORS)) self.assertTrue(f.has_error(NON_FIELD_ERRORS, 'password_mismatch')) self.assertFalse(f.has_error(NON_FIELD_ERRORS, 'anything')) def test_dynamic_construction(self): # It's possible to construct a Form dynamically by adding to the self.fields # dictionary in __init__(). Don't forget to call Form.__init__() within the Loading Loading
django/forms/forms.py +9 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,15 @@ class BaseForm(object): if field in self.cleaned_data: del self.cleaned_data[field] def has_error(self, field, code=None): if code is None: return field in self.errors if field in self.errors: for error in self.errors.as_data()[field]: if error.code == code: return True return False def full_clean(self): """ Cleans all of self.data and populates self._errors and Loading
docs/ref/forms/api.txt +11 −0 Original line number Diff line number Diff line Loading @@ -182,6 +182,17 @@ when defining form errors. Note that ``Form.add_error()`` automatically removes the relevant field from ``cleaned_data``. .. method:: Form.has_error(field, code=None) .. versionadded:: 1.8 This method returns a boolean designating whether a field has an error with a specific error ``code``. If ``code`` is ``None``, it will return ``True`` if the field contains any errors at all. To check for non-field errors use :data:`~django.core.exceptions.NON_FIELD_ERRORS` as the ``field`` parameter. Behavior of unbound forms ~~~~~~~~~~~~~~~~~~~~~~~~~ Loading
docs/releases/1.8.txt +3 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,9 @@ Forms * Form widgets now render attributes with a value of ``True`` or ``False`` as HTML5 boolean attributes. * The new :meth:`~django.forms.Form.has_error()` method allows checking if a specific error has happened. Internationalization ^^^^^^^^^^^^^^^^^^^^ Loading
tests/forms_tests/tests/test_forms.py +34 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import datetime import json import warnings from django.core.exceptions import NON_FIELD_ERRORS from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import RegexValidator from django.forms import ( Loading Loading @@ -739,6 +740,39 @@ class FormsTestCase(TestCase): with six.assertRaisesRegex(self, ValueError, "has no field named"): f.add_error('missing_field', 'Some error.') def test_has_error(self): class UserRegistration(Form): username = CharField(max_length=10) password1 = CharField(widget=PasswordInput, min_length=5) password2 = CharField(widget=PasswordInput) def clean(self): if (self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']): raise ValidationError( 'Please make sure your passwords match.', code='password_mismatch', ) f = UserRegistration(data={}) self.assertTrue(f.has_error('password1')) self.assertTrue(f.has_error('password1', 'required')) self.assertFalse(f.has_error('password1', 'anything')) f = UserRegistration(data={'password1': 'Hi', 'password2': 'Hi'}) self.assertTrue(f.has_error('password1')) self.assertTrue(f.has_error('password1', 'min_length')) self.assertFalse(f.has_error('password1', 'anything')) self.assertFalse(f.has_error('password2')) self.assertFalse(f.has_error('password2', 'anything')) f = UserRegistration(data={'password1': 'Bonjour', 'password2': 'Hello'}) self.assertFalse(f.has_error('password1')) self.assertFalse(f.has_error('password1', 'required')) self.assertTrue(f.has_error(NON_FIELD_ERRORS)) self.assertTrue(f.has_error(NON_FIELD_ERRORS, 'password_mismatch')) self.assertFalse(f.has_error(NON_FIELD_ERRORS, 'anything')) def test_dynamic_construction(self): # It's possible to construct a Form dynamically by adding to the self.fields # dictionary in __init__(). Don't forget to call Form.__init__() within the Loading