Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic Way to Transfer Django Model Validation Errors to a Form

Tags:

python

django

Please help me understand if the following choices I have made are idiomatic/good and if not, how to improve.

1) Model Validation over Form Validation
I prefer to use the new model validation over form validation whenever possible as it seems a more DRY and fundamental way to create rules for the data. Two examples for a simple calendar-entry model:

  • "start must be before end"
  • "period must be less than (end-start)"

Is it idiomatic/good to put those at the model level so they don't have to be put into forms? If ModelForm is the best answer, then what about the case of using multiple models in the same form?
(edit: I didn't realize that multiple ModelForms can actually be used together)

2) Transferring Model Validation to a Form (not ModelForm)
(edit: It turns out reinventing the plumbing between model validation and form validation is not necessary in my situation and the solutions below show why)
Let's assume for a moment that any model validation errors I have can be directly transferred and displayed directly to the user (i.e. ignore translating model validation errors to user-friendly form validation errors).

This is one working way I came up with to do it (all in one place, no helper functions):

view_with_a_form:
...
if form.is_valid():
    instance = ...
    ...
    #save() is overridden to do full_clean with optional exclusions
    try: instance.save()
    except ValidationError e:
        nfe= e.message_dict[NON_FIELD_ERRORS]
        #this is one big question mark:
        instance._errors['__all__'] = ErrorList(nfe)
#this is the other big question mark. seems unnatural
if form.is_valid()
    return response...
... #other code in standard format
#send the user the form as 1)new 2)form errors 3)model errors
return form

As commented in the code:
a) Is this an idiomatic/good way to transfer model errors to a form?

b) Is this an idiomatic/good way to test for new "form" errors?

Note: This example uses non-field errors, but I think it could equally apply to field errors.

like image 394
KobeJohn Avatar asked Oct 12 '11 07:10

KobeJohn


People also ask

How do I display validation error in Django?

To display the form errors, you use form. is_valid() to make sure that it passes validation. Django says the following for custom validations: Note that any errors raised by your Form.

How do I increase validation error in Django?

To create such an error, you can raise a ValidationError from the clean() method. For example: from django import forms from django. core.

What is clean method in Django?

clean() This method should be used to provide custom model validation and to modify attributes on your model if desired.

How do you remove this field is required Django?

If yes try to disable this behavior, set the novalidate attribute on the form tag As <form action="{% url 'new_page' %}", method="POST" novalidate> in your html file.


1 Answers

[Edited - hope this answers your comments]

I'll be brief and direct but do not want be impolite :)

1) Model Validation over Form Validation

I guess that the rule of thumb could be that as long as the rule is really associated with the model, yes, it's better to do validation at model level.

For multiple-model forms, please checkout this other SO question: Django: multiple models in one template using forms, not forgetting the attached link which is slightly old but still relevant on the dryest way to achieve it. It's too long to re-discuss it all here!

2)

  • a) No! You should derive your form from a ModelForm that will perform model validation for you -> you do not need to call model validation yourself
  • b) No! If you want to validate a model you should not try and save it; you should use full_clean -> so if your ModelForm is valid, then you know the model is valid too and you can save.

And yes, these answers still apply even with multi-model forms.

So what you should do is:

  • Still use ModelForm
  • do not worry about validating a model, because a ModelForm will do that for you.

In general if you find yourself doing some plumbing with django it's because there's another, simpler way to do it!

The 2nd pointer should get you started and actually simplify your code a lot...

like image 118
Stefano Avatar answered Oct 17 '22 14:10

Stefano