Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Externally add form errors in Django

I have a Django form that will add an entry to a database with a unique constraint on one of the columns. If the submission happens to attempt creation of a duplicate, I get a django.db.utls.IntegrityError stating I violated the unique constraint (thankfully).

When processing Django forms, there are a number of ways to validate:

  1. Override the form class' clean method
  2. Override the form class' clean_<field> method

If the clear_<field> method raises a django.forms.ValidationError, the error message will be appended to a list in the _errors dictionary under the field's name. When using the clean method, errors should be manually inserted into the _errors dict.

Now, the clean and clean_<field> methods don't sound like a nice place to put code that has side effects, and I fear that checking at this moment whether the value is unique does not guarantee I won't get IntegrityErrors. I would prefer to actually try and create the row in the database and signal a form error when a constraint is violated.

My main problem is that forms expose a public property errors which is read-only. Therefore, I should, according to the docs, add a method in my form that does all the work, try to insert in the database and register an error when an IntegrityError is raised. Because the action that processes the form after validation requires lots of other data, I don't want to put the code inside the form class itself.

Is there any other (documented or not) way to go about adding an entry in the errors dict from outside the class, or should I simply access the _errors "private" variable and be happy with that? I know this sounds like an OOP breach, but creating an extra method just to access this "private" variable does not seem to me like it shields anybody from anything.

Edit: Seems like someone else already raised a similar question, but it seems the answers pointed to manual insertion into _errors...

like image 795
André Caron Avatar asked Oct 11 '10 03:10

André Caron


People also ask

What is Is_valid () in Django?

The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.

What method can you use to check if form data has changed when using a form instance?

Checking which form data has changed Use the has_changed() method on your Form when you need to check if the form data has been changed from the initial data. has_changed() will be True if the data from request. POST differs from what was provided in initial or False otherwise. The result is computed by calling Field.

How does form Is_valid work in Django?

A Form instance has an is_valid() method, which runs validation routines for all its fields. When this method is called, if all fields contain valid data, it will: return True. place the form's data in its cleaned_data attribute.

What is Django cleaned_data?

cleaned_data returns a dictionary of validated form input fields and their values, where string primary keys are returned as objects. form. data returns a dictionary of un-validated form input fields and their values in string format (i.e. not objects).


1 Answers

For now, a simple solution is the following:

try:
    # Try to save model instance, which might throw `IntegrityError`.
    # ...
except django.db.utils.IntegrityError:
    # The form passed validation so it has no errors.
    # Use the `setdefault` function just in case.
    errors = django.forms.util.ErrorList()
    errors = form._errors.setdefault(
        django.forms.forms.NON_FIELD_ERRORS, errors)
    errors.append('Sorry, this username is already in use.')
like image 132
André Caron Avatar answered Nov 09 '22 14:11

André Caron