3👍
✅
A Form instance is either bound to a set of data, or unbound.
- If it’s bound to a set of data, it’s capable of validating that data
- If it’s unbound, it cannot do validation
class Form:
...
def is_valid(self):
"""Return True if the form has no errors, or False otherwise."""
return self.is_bound and not self.errors
With a bound Form instance, call the .is_valid()
method to run validation and return a boolean designating whether the form is bound and the data is valid(has no errors)
self.is_bound
check whether the data is passed to formself.errors
check the property error, which will trigger the full validation process(if_errors
not populated yet)
class Form:
...
@property
def errors(self):
"""Return an ErrorDict for the data provided for the form."""
if self._errors is None:
self.full_clean()
return self._errors
After that, self.full_clean
will trigger a series of validation, including cleaning individual field(self._clean_fields
), whole form(self._clean_form
), and post clean hooker(_self._post_clean
).
In the process, any client side code that raises ValidationError
(i.e raise ValidationError("Email already exists")
) will be properly handled by Form
itself by adding these errors to the form._errors
attribute, which eventually, you could access through form.errors
property
class BaseForm:
...
def full_clean(self):
"""
Clean all of self.data and populate self._errors and self.cleaned_data.
"""
self._errors = ErrorDict()
self.cleaned_data = {}
# these three methods will populate the _errors, cleaned_data attribute
self._clean_fields()
self._clean_form()
self._post_clean()
def _clean_fields(self):
# simplified for demonstration purpose
for name, field in self.fields.items():
try:
validate(field)
# your ValidationError("Email already exists") will be catched here
except ValidationError as e:
# add errors to `form._error` dict
self.add_error(name, e)
Source:stackexchange.com