当前位置 博文首页 > Silent丿丶黑羽:Django(44)drf序列化源码分析

    Silent丿丶黑羽:Django(44)drf序列化源码分析

    作者:Silent丿丶黑羽 时间:2021-06-04 18:27

    序列化与反序列化

    ??一般后端数据返回给前端的数据格式都是json格式,简单易懂,但是我们使用的语言本身并不是json格式,像我们使用的Python如果直接返回给前端,前端用的javascript语言是识别不出的,所以我们需要把python语言转换为通用的json格式的数据,在django中就是将orm模型或者queryset对象转换成字典,再由字典转换成json,整个过程就是序列化。

    ??当用户通过在form表单中填写的数据,发送请求给后端,将数据提交给后端数据库,这个过程就是反序列化。反序列化的时候,我们需要去验证前端提交的数据是否符合后端制定的规范,符合才进行入库。
     

    drf的序列化类

    drf的序列化类有3个

    • Serializer
    • ModelSerializer(使用最多的)
    • ListSerializer

    我们使用最多的就是ModelSerializer,这三个序列化类都继承自BaseSerializer,虽然我们项目中99%都是使用的ModelSerializer,但是光知道怎么使用,是没有灵魂的,我们还需要去了解源码,多看源码能迅速提高代码能力。
     

    BaseSerializer源码分析

    源码如下:

    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)
    

    我们分析几个重要的方法,没必要每个方法都了解,分析的都是后面要用到的
     

    __init__方法

    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)
    

    初始化方法,有4个参数

    • self:本身自己
    • instance:实例,默认为None
    • data:数据,默认为empty
    • **kwargs:不定长字典
       

    create

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

    定义了一个create方法,参数为validated_data,方法抛出了一个异常,意思是create方法没有定义,如果要继承BaseSerializer,那就必须定义create方法,否则就会抛出异常
     

    update

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

    定义了一个update方法,有2个参数

    • instance:实例,更新数据的时候,需要知道更新的是哪个实例化对象
    • validated_data:已验证的数据,前端传入的字段需要进行验证

    此方法抛出了一个异常,意思是update方法没有定义,如果要继承BaseSerializer,那就必须定义update方法,否则就会抛出异常
     

    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)
    

    这个方法是验证从前端传输过来的字段是否验证成功,如果我们的实例化对象没有传入data参数,将会无法调用is_valid,这个方法大多数用在反序列化的时候
     

    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
    
    bk