Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fixed #22318 -- Added Form.has_error() to easily check if a given error ... #2466

Closed
wants to merge 1 commit into from

2 participants

@loic
Collaborator

...has happened.

@timgraham
Owner

merged in 7ac8380.

@timgraham timgraham closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 23, 2014
  1. @loic
This page is out of date. Refresh to see the latest.
View
9 django/forms/forms.py
@@ -334,6 +334,15 @@ def add_error(self, field, error):
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
View
11 docs/ref/forms/api.txt
@@ -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`` param.
+
Behavior of unbound forms
~~~~~~~~~~~~~~~~~~~~~~~~~
View
3  docs/releases/1.8.txt
@@ -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
^^^^^^^^^^^^^^^^^^^^
View
34 tests/forms_tests/tests/test_forms.py
@@ -6,6 +6,7 @@
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 (
@@ -739,6 +740,39 @@ def clean(self):
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
Something went wrong with that request. Please try again.