Django (44) drf serialization source code analysis

Serialization and deserialization

General back-end data back to the front of the data format is jsonthe format, easy to understand, but the language we use is not in itself jsonform, as we use Pythonif returned directly to the front, with the front end of the javascriptlanguage is not recognize, so we The pythonlanguage needs to be converted into jsondata in a common format, in djangowhich the ormmodel or querysetobject is converted into a dictionary, and then converted into a dictionary json. The whole process is serialization.

When the user formsends a request to the back-end through the data filled in the form, and submits the data to the back-end database, this process is deserialization. When deserializing, we need to verify whether the data submitted by the front-end meets the specifications set by the back-end, and then enter the database only if it meets the specifications.

serialization class of drf

drfThere are 3 serialization classes

  • Serializer
  • ModelSerializer (most used)
  • ListSerializer

What we use the most is ModelSerializerthat these three serialization classes are inherited from them BaseSerializer. Although 99% of our projects are used ModelSerializer, there is no soul if we only know how to use it. We also need to understand the source code, and see the source code quickly. Improve code ability.

BaseSerializerSource code analysis

The source code is as follows:

class BaseSerializer(Field):    def __init__(self, instance=None, data=empty, **kwargs):         def __new__(cls, *args, **kwargs)    def __class_getitem__(cls, *args, **kwargs)    @classmethod    def many_init(cls, *args, **kwargs):     def to_internal_value(self, data):     def to_representation(self, instance):     def update(self, instance, validated_data):     def create(self, validated_data):     def save(self, **kwargs):     def is_valid(self, raise_exception=False):     @property    def data(self):     @property    def errors(self)    @property    def validated_data(self)

We analyze several important methods, it is not necessary to understand each method, the analysis is to be used later

__init__ method

def __init__(self, instance=None, data=empty, **kwargs):    self.instance = instance     if data is not empty:        self.initial_data = data    self.partial = kwargs.pop('partial', False)    self._context = kwargs.pop('context', {})    kwargs.pop('many', None)    super().__init__(**kwargs)

Initialization method, there are 4 parameters

  • self: oneself
  • instance: instance, the default isNone
  • data: data, the default isempty
  • **kwargs: variable length dictionary

create

def create(self, validated_data):    raise NotImplementedError('`create()` must be implemented.')

A createmethod is defined , the parameter is validated_data, the method throws an exception, which means that the createmethod is not defined, if you want to inherit BaseSerializer, then you must define the createmethod, otherwise an exception will be thrown

update

def update(self, instance, validated_data):    raise NotImplementedError('`update()` must be implemented.')

Defines a updatemethod with 2 parameters

  • instance: Instance, when updating data, you need to know which instantiated object is being updated
  • validated_data: Verified data, the fields passed in from the front end need to be verified

This method throws an exception, which means that the updatemethod is not defined. If you want to inherit BaseSerializer, you must define the updatemethod, otherwise an exception will be thrown

is_valid

def is_valid(self, raise_exception=False):    # 如果self对象没有initial_data属性,那么将无法调用该方法,如果需要有initial_data,那么实例化对象必须传入data参数    assert hasattr(self, 'initial_data'), (        'Cannot call `.is_valid()` as no `data=` keyword argument was '        'passed when instantiating the serializer instance.'    )     if not hasattr(self, '_validated_data'):        try:            self._validated_data = self.run_validation(self.initial_data)        except ValidationError as exc:            self._validated_data = {}            self._errors = exc.detail        else:            self._errors = {}     if self._errors and raise_exception:        raise ValidationError(self.errors)     return not bool(self._errors)

This method is to verify whether the field transmitted from the front end is successfully verified. If our instantiated object does not pass in dataparameters, it will not be able to be called is_valid. This method is mostly used in deserialization.

save

def save(self, **kwargs):    # 调用save()方法前必须先调用is_valid()    assert hasattr(self, '_errors'), (        'You must call `.is_valid()` before calling `.save()`.'    )    # 不能对无效的数据调用save()方法    assert not self.errors, (        'You cannot call `.save()` on a serializer with invalid data.'    )    # 防止没有正确使用save方法    # Guard against incorrect use of `serializer.save(commit=False)`    assert 'commit' not in kwargs, (        "'commit' is not a valid keyword argument to the 'save()' method. "        "If you need to access data before committing to the database then "        "inspect 'serializer.validated_data' instead. "        "You can also pass additional keyword arguments to 'save()' if you "        "need to set extra attributes on the saved model instance. "        "For example: 'serializer.save(owner=request.user)'.'"    )    # 访问serializer.data后就不能调用save方法了,如果你需要在提交到数据库之前访问数据,那么请使用serializer.validated_data    assert not hasattr(self, '_data'), (        "You cannot call `.save()` after accessing `serializer.data`."        "If you need to access data before committing to the database then "        "inspect 'serializer.validated_data' instead. "    )    # 创建已验证的数据对象    validated_data = {**self.validated_data, **kwargs}        # 如果instance不为空    if self.instance is not None:        # instance对象将更新为validated_data里的内容        self.instance = self.update(self.instance, validated_data)        assert self.instance is not None, (            '`update()` did not return an object instance.'        )    else:        # 如果instance为空,那么则创建对象,对象的内容为validated_data        self.instance = self.create(validated_data)        assert self.instance is not None, (            '`create()` did not return an object instance.'        )     return self.instance