75
Django has a model validation system in place since version 1.2.
In comments sebpiq says “Ok, now there is a place to put model validation … except that it is run only when using a ModelForm! So the question remains, when it is necessary to ensure that validation is respected at the db-level, what should you do? Where to call full_clean?”
It’s not possible via Python-level validation to ensure that validation is respected on the db level. The closest is probably to call full_clean
in an overridden save
method. This isn’t done by default, because it means everybody who calls that save method had now better be prepared to catch and handle ValidationError
.
But even if you do this, someone can still update model instances in bulk using queryset.update()
, which will bypass this validation. There is no way Django could implement a reasonably-efficient queryset.update()
that could still perform Python-level validation on every updated object.
The only way to really guarantee db-level integrity is through db-level constraints; any validation you do through the ORM requires the writer of app code to be aware of when validation is enforced (and handle validation failures).
This is why model validation is by default only enforced in ModelForm
– because in a ModelForm there is already an obvious way to handle a ValidationError
.
7
I think you want this ->
from django.db.models.signals import pre_save
def validate_model(sender, **kwargs):
if 'raw' in kwargs and not kwargs['raw']:
kwargs['instance'].full_clean()
pre_save.connect(validate_model, dispatch_uid='validate_models')
(Copied from http://djangosnippets.org/snippets/2319/)
- [Django]-How to avoid AppConfig.ready() method running twice in Django
- [Django]-What is the right way to validate if an object exists in a django view without returning 404?
- [Django]-Can we append to a {% block %} rather than overwrite?
3
The root issue for this, is that the validation should happen on models. This has been discussed for quite some time in django (search form model aware validation on the dev mailing list). It leads to either duplication or things escaping validation before hitting the db.
While that doesn’t hit trunk, Malcolm’s “poor man’s model validation solution” is probably the cleanest solution to avoid repeating yourself.
- [Django]-Django Admin – Disable the 'Add' action for a specific model
- [Django]-Set Django IntegerField by choices=… name
- [Django]-Why is assertDictEqual needed if dicts can be compared by `==`?
1
If I understand you “clearly” – you must override function get_db_prep_save instead of to_python
- [Django]-Why is assertDictEqual needed if dicts can be compared by `==`?
- [Django]-How to server HTTP/2 Protocol with django
- [Django]-How do I filter ForeignKey choices in a Django ModelForm?