17

I think Django's model validation is a little inconvenient for those models that don't use built-in ModelForm, though not knowing why.

Firstly, full_clean() needs called manually.

Note that full_clean() will not be called automatically when you call your model’s save() method, nor as a result of ModelForm validation.In the case of ModelForm validation, Model.clean_fields(), Model.clean(), and Model.validate_unique() are all called individually.You’ll need to call full_clean manually when you want to run one-step model validation for your own manually created models.

Secondly, validators are used in built-in ModelForm.

Note that validators will not be run automatically when you save a model, but if you are using a ModelForm, it will run your validators on any fields that are included in your form.

There are great demands when you need to do data validation before saving data into databases. And obviously I'd prefer to make it in model, rather than views. So, are there any good ideas to implement this gracefully in Django 1.5?

Francisco
  • 10,918
  • 6
  • 34
  • 45
ray6080
  • 873
  • 2
  • 10
  • 25

1 Answers1

31

Even though the idea of enforcing validation on Model level seems right, Django does not do this by default for various reasons. Except for some backward-compatibility problems, the authors probably don't want to support this because they fear this could create a false feeling of safety when in fact your data are not guaranteed to be always validated. Some ORM methods (e.g. bulk_create or update) don't call save() and thus are unable to validate your models. In other words, it is hard to guarantee the validation, thus they've decided not to pretend it.

If you need this for multiple models, you can create a simple mixin that overrides the save() method and calls full_clean() before super. Do note that this might cause the validation to be run twice in some cases, like when using ModelForm. It might not be that of an issue though if your validation routines are side-effect free and cheap to run.

For more info, please see these answers:

Community
  • 1
  • 1
knaperek
  • 2,113
  • 24
  • 39
  • 1
    So model level validation is not encouraged, and at the same time CHECK constraints in databases are not supported. If i'm not writing webforms there isnt a clear solution. – kert Aug 23 '15 at 03:02
  • 1
    I'd say the opposite - it is actually encouraged, just not supported by default (due to historical reasons). It's easy to make it default in your project though - just create a mixin or a new base Model class, overriding the `save` method and calling `full_clean` inside. – knaperek Aug 26 '15 at 06:25
  • 6
    I have done the .save/full_clean() route. The problem is that django queryset provides multiple default functions that bypass model validation completely ( .update on queryset and a few others ) So you have to enforce a pretty strict discipline about how the model validation functions are supposed to be called, when and also about which database updtate methods not to use at all. So you can spend a lot of time writing all that model validation code, test it thoroughly, but you can still end up with inconsistencies easily. – kert Aug 26 '15 at 21:54
  • Yes, and that is one of the reasons why it is not included in the original Django implementation - to prevent false sense of safety. You have to always keep in mind all the ways that you commonly manipulate your objects, if those can possibly make them invalid. Sometimes a strict design decision can help; i.e. in case you absolutely possitively need to ensure object validity, you only manipulate such objects via `save()` method and stay away from bulk operations like `.update()`. – knaperek Sep 04 '15 at 21:38