Where should i do the django validations for objects and fields?

2024/10/2 22:24:50

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)

Answer

For model-level validation, there is the Model.clean method.

It is called if you are using ModelForm (which is used by default in admin), 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 in Serializer.validate (as the doc suggests). You can do it via a serializer mixin:

class ValidateModelMixin(object)def validate(self, attrs):attrs = super().validate(attrs)obj = self.Meta.model(**attrs)obj.clean()return attrsclass SomeModelSerializer(ValidateModelMixin, serializers.ModelSerializer):#...class Meta:model = SomeModel

or write a validator:

class DelegateToModelValidator(object):def set_context(self, serializer):self.model = serializer.Meta.modeldef __call__(self, attrs):obj = self.model(**attrs)obj.clean()class SomeModelSerializer(serializers.ModelSerializer):#...class Meta:model = SomeModelvalidators = (DelegateToModelValidator(),)

Caveats:

  • an extra instantiation of your models just to call clean
  • you will still have to add the mixin/validator to your serializers
https://en.xdnf.cn/q/70799.html

Related Q&A

Why does bytes.fromhex() treat some hex values strangely?

Im trying to use the socket library in Python to send bytes of two hex digits to a piece of hardware programmed to accept them. To create the bytes from a user-entered string of hex digits, Im trying …

Extracting beats out of MP3 music with Python

What kind of solutions are there to analyze beats out of MP3 music in Python? The purpose of this would be to use rhythm information to time the keyframes of generated animation, export animation as v…

Switch to popup in python using selenium

How do I switch to a popup window in the below selenium program. Ive looked up for all possible solutions but havent been able to get my head around them. Please help!!from selenium import webdriver fr…

Segmentation fault while redirecting sys.stdout to Tkinter.Text widget

Im in the process of building a GUI-based application with Python/Tkinter that builds on top of the existing Python bdb module. In this application, I want to silence all stdout/stderr from the consol…

Why do pandas and dask perform better when importing from CSV compared to HDF5?

I am working with a system that currently operates with large (>5GB) .csv files. To increase performance, I am testing (A) different methods to create dataframes from disk (pandas VS dask) as well a…

is there any pool for ThreadingMixIn and ForkingMixIn for SocketServer?

I was trying to make an http proxy using BaseHttpServer which is based on SocketServer which got 2 asynchronous Mixins (ThreadingMixIn and ForkingMixIn)the problem with those two that they work on each…

Python - Read data from netCDF file with time as seconds since beginning of measurement

I need to extract values from a netCDf file. I am pretty new to python and even newer this file format. I need to extract time series data at a specific location (lat, lon). I have found that there is …

PyQt Multiline Text Input Box

I am working with PyQt and am attempting to build a multiline text input box for users. However, when I run the code below, I get a box that only allows for a single line of text to be entered. How to …

Calculate the sum of model properties in Django

I have a model Order which has a property that calculates an order_total based on OrderItems linked by foreign key.I would like to calculate the sum of a number of Order instances order_total propertie…

Set Host-header when using Python and urllib2

Im using my own resolver and would like to use urllib2 to just connect to the IP (no resolving in urllib2) and I would like set the HTTP Host-header myself. But urllib2 is just ignoring my Host-header:…