20

Is it typical to separate input validation from model-level validation in Django projects? For example, validating that a username fits naming criteria would be input validation, and verifying that the user isn't already in the database would be model-level validation.

I've been looking at a co-worker's code, and they put both types of validation in a form class (in forms.py). Is this the typical setup, or is it more common for the model-level validation to appear in the model or view?

Or is there a better way to be approaching this-- such as using a ModelForm? I'm rather new to Django and trying to learn what is the recommended pattern for this situation.

Ben G
  • 26,091
  • 34
  • 103
  • 170

2 Answers2

16

This is a very interesting question (for me).

In my opinion, all validation code should be moved to model code. This is the way to not break business rules. When validation code is in the model it is not possible to forget some validation in a new form or to have inconsistent rules in several forms.

I link to you 'Django, Raise a validation error in a model's save method' question that is related to yours. Below question you can see how move code validations from forms to model. I hope that this brief introduction can helps to you.

From what framework you come? How validation rules are writen in your enviromnent?

Community
  • 1
  • 1
dani herrera
  • 48,760
  • 8
  • 117
  • 177
  • 3
    I agree. Most things really can be thought of as "model-level" validation. You really don't ever want a username to hit the database if it doesn't match naming criteria. There are some things that will vary form-to-form, and that's where you want to validate on the form itself. You may have a fancy File model which holds file type in a field. Any type is ok at the model level, but in the photo upload form you want to limit it to png and jpeg, for instance. – dokkaebi Jan 29 '12 at 23:22
9

I don't agree with the accepted answer. I prefer to use model-level validation to avoid inconsistencies in models, and form-level validation for any site-specific restrictions.

Suppose we have a model for events, with datetime fields for the start and end time. Model validation would force us to have an end time that comes after the start time. However, I would leave it in the form to validate that the newly created event is not in the past. Therefore, if I ever have to add an event that occured in the past, I could use an admin-specific form that allows dates in the past, or simply add it straight to the database.

Thus, model validation should only check for values that are patently wrong. but if you ever need to do something funky (Unicode characters in a username for a bot, for example), it should let you do it, even if it's only through the admin or the shell. I've read an answer on StackOverflow that suggested always using forms in backend code, filling fields with code like form["field"] = "value", to benefit from consistent validation.

sleblanc
  • 3,821
  • 1
  • 34
  • 42
  • 1
    For your example scenario, you can have userId field on `event` table and allow fill form with past dates for some group users. For each example you post I can find a counterexample like this ;) But this is my approach, I'm sure than for some rules, form validation will be the best solution. – dani herrera Jan 02 '14 at 21:13
  • Of course you can also implement it in the model, but then you are baking in functionality into something that should be the form instead. If you want to re-use your Blog model elsewhere, why should it care if the post belongs to a user in a group named "admin"? Since this requirement can change from one site to another, it is best left to a form rather than the model itself. – sleblanc Sep 21 '15 at 16:36
  • perhaps, in the future, your web app will have a full rest api. Is just an example. Thanks about share your commet, is welcome. – dani herrera Sep 21 '15 at 16:49