I'm creating a django application which uses both the Django Rest Framework and the plain django-views as entrypoint for users.
I want to do validation both independant fields of my models, and on objects on a whole. For example:
Field: is the entered licence-plate a correct one based on a regex function. No relation to other fields.
Object: Is the entered zipcode valid for the given country. Relates to zipcode and country in the model.
For the DRF-API i use ModelSerializers which automatically call all the validators i have placed in my Model, for example:
class MyModel(models.Model):
licence_plate = CharField(max_length=20, validators=[LicencePlateValidator])
Since the validator is given in the model, the API POSTS (because i use a ModelSerializer), as well as the objects created in the django admin backend are validated.
But when i want to introduce object level validation i need to do that in the serializer's validate()-method, which means objects are only validated in the API.
I'll have to override the model's save method too, to validate the objects created in the Django admin page.
Question: This seems a bit messy to me, is there a single point where i can put the object-level validators so that they are run at the API and in the admin-page, like i did with the field-level validation (I only have to put them in my model-declaration and everything is handled)
For model-level validation, there is the
Model.clean
method.It is called if you are using
ModelForm
(which is used by default inadmin
), so this solves django views and admin parts.On the other hand, DRF does not call models'
clean
automatically, so you will have to do it yourself inSerializer.validate
(as the doc suggests). You can do it via a serializer mixin:or write a validator:
Caveats:
clean
You can create a separate function
validate_zipcode_with_country(zipcode, country)
which will take 2 argumentszipcode
andcountry
.Then, we will call this method in the serializer's
validate()
and in our model'sclean()
.Then in your
serializers.py
, you need to call this function in yourvalidate()
function.Similarly, you need to override the model's
clean()
and call this function.