DRF源码-serializers

class BaseSerializer(Field)

"""
The BaseSerializer class provides a minimal class which may be used
for writing custom serializer implementations.
这个类提供一个最小化的类,可以用来写自定义的序列化实现

Note that we strongly restrict the ordering of operations/properties
that may be used on the serializer in order to enforce correct usage.
序列化上会用到的操作/属性的顺序是被限制的,为了正确的使用

In particular, if a `data=` argument is passed then:
如果传递data=这个参数

.is_valid() - Available.可用
.initial_data - Available.可用
.validated_data - Only available after calling `is_valid()`调用is_valid之后可用
.errors - Only available after calling `is_valid()`
.data - Only available after calling `is_valid()`

If a `data=` argument is not passed then:
一般来水不会传递data这个参数
.is_valid() - Not available.
.initial_data - Not available.
.validated_data - Not available.
.errors - Not available.
.data - Available.
"""

  

    def __init__(self, instance=None, data=empty, **kwargs):    #初始化,传入instance参数(一个model class的实例)
        self.instance = instance    #instance给到self
        if data is not empty:
            self.initial_data = data
        self.partial = kwargs.pop('partial', False)     #将额外的字典参数中,partial,context给到self,如果没有,给出默认值
        self._context = kwargs.pop('context', {})
        kwargs.pop('many', None)    #将many这个key删除
        super().__init__(**kwargs)  #继承父类的其余属性

  

    # 对self.data属性函数化,为了加判断
    # 将instance转化为data
    @property
    def data(self):
        if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):
            msg = (
                'When a serializer is passed a `data` keyword argument you '
                'must call `.is_valid()` before attempting to access the '
                'serialized `.data` representation.\n'
                'You should either call `.is_valid()` first, '
                'or access `.initial_data` instead.'
            )
            raise AssertionError(msg)

        if not hasattr(self, '_data'):
            if self.instance is not None and not getattr(self, '_errors', None):
                self._data = self.to_representation(self.instance)
            elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
                self._data = self.to_representation(self.validated_data)
            else:
                self._data = self.get_initial()
        return self._data

  


class Serializer(BaseSerializer, metaclass=SerializerMetaclass):

    # 继承父类的data属性,然后调用ReturnDict函数返回
    @property
    def data(self):
        ret = super().data
        return ReturnDict(ret, serializer=self)

  

app目录

serializer.py

# 创建serializers.Serializer的子类
# 几个field是Fields.py里Field的几个子类
class ColorsSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    colors = serializers.CharField(max_length=10)
    def create(self, validated_data):
        return Colors.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.colors = validated_data.get('colors', instance.colors)
        instance.save()
        return instance

 

views.py

def test(request):
    color = Colors(id=2,colors='red')       #color为一个xxx.models.Colors的instance
    print(color)                            #一个instance,由该model类的__str__(self)的返回值决定
    serializer = ColorsSerializer(instance=color)    #将这个instance传入序列化类,返回一个序列化实例
    print(serializer.data)                  # <class 'rest_framework.utils.serializer_helpers.ReturnDict'>
    print(type(serializer.data))            # {'id': 2, 'colors': 'red'}
    return HttpResponse('done')

  

 

class ModelSerializer(Serializer):

    """
    A `ModelSerializer` is just a regular `Serializer`, except that:

    * A set of default fields are automatically populated.
    * A set of default validators are automatically populated.
    * Default `.create()` and `.update()` implementations are provided.
    *将自动填充一组默认字段。
    *将自动填充一组默认验证器。
    *提供了默认的`.create()`和`.update()`实现。elds
    The process of automatically determining a set of serializer fields
    based on the model fields is reasonably complex, but you almost certainly
    don't need to dig into the implementation.

    If the `ModelSerializer` class *doesn't* generate the set of fields that
    you need you should either declare the extra/differing fields explicitly on
    the serializer class, or simply use a `Serializer` class.
    如果“modelserializer”class没有生成所需字段,我应该在序列化类明确申明额外字段
    或者直接使用Serializer类
    """

 

    # Default `create` and `update` behavior...
    def create(self, validated_data):
        """
        We have a bit of extra checking around this in order to provide
        descriptive messages when something goes wrong, but this method is
        essentially just:
        我们在这里有一些额外的检查,为了当发生错误时可以提供一些可描述的信息。
        但这个方法,本质上就是:
            return ExampleModel.objects.create(**validated_data)

        If there are many to many fields present on the instance then they
        cannot be set until the model is instantiated, in which case the
        implementation is like so:
        如果实例中有多对对字段,需要以下实现:先把字段从validated_data pop出来,
            example_relationship = validated_data.pop('example_relationship')
            instance = ExampleModel.objects.create(**validated_data)
            instance.example_relationship = example_relationship
            return instance

        The default implementation also does not handle nested relationships.
        If you want to support writable nested relationships you'll need
        to write an explicit `.create()` method.
        """
        raise_errors_on_nested_writes('create', self, validated_data)

        # 在Meta嵌套类中的model属性
        ModelClass = self.Meta.model

        # Remove many-to-many relationships from validated_data.
        # They are not valid arguments to the default `.create()` method,
        # as they require that the instance has already been saved.
        # 把model类的字段信息给到info
        # 处理多对多字段
        info = model_meta.get_field_info(ModelClass)
        many_to_many = {}
        for field_name, relation_info in info.relations.items():
            if relation_info.to_many and (field_name in validated_data):
                many_to_many[field_name] = validated_data.pop(field_name)
        # 表插入,返回到instance
        try:
            instance = ModelClass._default_manager.create(**validated_data)
        except TypeError:
            tb = traceback.format_exc()
            msg = (
                'Got a `TypeError` when calling `%s.%s.create()`. '
                'This may be because you have a writable field on the '
                'serializer class that is not a valid argument to '
                '`%s.%s.create()`. You may need to make the field '
                'read-only, or override the %s.create() method to handle '
                'this correctly.\nOriginal exception was:\n %s' %
                (
                    ModelClass.__name__,
                    ModelClass._default_manager.name,
                    ModelClass.__name__,
                    ModelClass._default_manager.name,
                    self.__class__.__name__,
                    tb
                )
            )
            raise TypeError(msg)

        # Save many-to-many relationships after the instance is created.
        if many_to_many:
            for field_name, value in many_to_many.items():
                field = getattr(instance, field_name)
                field.set(value)

        return instance

  

    # 在instance上设定每个属性,然后save
    def update(self, instance, validated_data):
        raise_errors_on_nested_writes('update', self, validated_data)
        info = model_meta.get_field_info(instance)

        # Simply set each attribute on the instance, and then save it.
        # Note that unlike `.create()` we don't need to treat many-to-many
        # relationships as being a special case. During updates we already
        # have an instance pk for the relationships to be associated with.
        m2m_fields = []
        for attr, value in validated_data.items():
            if attr in info.relations and info.relations[attr].to_many:
                m2m_fields.append((attr, value))
            else:
                setattr(instance, attr, value)

        instance.save()

        # Note that many-to-many fields are set after updating instance.
        # Setting m2m fields triggers signals which could potentialy change
        # updated instance and we do not want it to collide with .update()
        for attr, value in m2m_fields:
            field = getattr(instance, attr)
            field.set(value)

        return instance

    # Determine the fields to apply...

  

app目录

serializers.py

class ColorsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Colors
        fields = ('url', 'id', 'colors')

  

views.py

def test(request):
    color = Colors(id=2,colors='red')       
    print(color)                            
    serializer = ColorsSerializer(instance=color,context={'request': request})    
    print(serializer.data)                  
    print(type(serializer.data))         
    return HttpResponse('done')

  

 几种多表操作的field应用

读取外键的某个字段

# Clothes的color是外键,默认情况下,color字段会对应母表的主键,id。
# 使用SlugRelatedField可以指向外键,slug_field表示获取哪个字段返回给color
# 这里color这个属性就被重写了
class ClothesSerializer(serializers.ModelSerializer):
    color = serializers.SlugRelatedField(queryset=Colors.objects.all(), slug_field='colors_cn')
    class Meta:
        model = Clothes
        fields = ('url', 'id', 'color', 'desc')

  

posted @ 2019-08-01 13:38  jabbok  阅读(514)  评论(0编辑  收藏  举报