drf 序列化源码,案例详解


本分栏还有一些drf的其他详解,不懂的可以自行查看

1,什么是序列化(serializers)

serializers是什么?官网是这样的”Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. “翻译出来就是,将复杂的数据结构,例如ORM中的QuerySet或者Model实例对象转换成Python内置的数据类型,从而进一步方便数据和json,xml等格式的数据进行交互。

2,案例分析

本案例都是小白一个字一个字手打出来的,快点赞吧
models

class Goods(BaseModel):
    '''商品模型'''
    
    name = models.CharField(max_length=20, unique=True, verbose_name='商品名称')
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='商品价格')
    centers = models.BooleanField(default=False, verbose_name='是否发布商品中心')
    create_user = models.ForeignKey('auth.user', on_delete=models.CASCADE, related_name='createuser',verbose_name='创建管理员')
    goodtype = models.ForeignKey('GoodType',to_field='name',on_delete=models.CASCADE,related_name='typeid',null=True,blank=True)

    class Meta:
        db_table = 'goods' 
        verbose_name = '商品'

    def __str__(self):
        return self.name

这是是我的序列器

class listSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.IntegerField()
    create_time = serializers.DateTimeField()
    create_user = serializers.CharField()
    goodtype = serializers.CharField()

这是views

class listViews(APIView):
    def get(self,request,*args,**kwargs):
        queryset = Goods.objects.all()
        res=UserinfoSerializer(instance=queryset,many=True) #instance接受queryset对象或者单个model对象,当有多条数据时候,使用many=True,单个对象many=False
        return Response(json.dumps(res.data,ensure_ascii=False))

这是序列化后的结果
在这里插入图片描述

这图片很大幅度的说明了serializer类的一些作用
在这里插入图片描述
这里补充一个知识点:

类是实例化之前会执行__new__方法,用于控制一个类生成实例的过程

子类没有__new__方法执行父类的__new__方法
__new__方法执行完以后执行__init__构造方法

3,源码分析

下面是Serializer的源码解析

class BaseSerializer(Field):
    """
    The BaseSerializer class provides a minimal class which may be used
    for writing custom serializer implementations.
	BaseSerializer类提供了可以使用的最小类
	用于编写自定义序列化器实现

    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()`
    .errors - Only available after calling `is_valid()`
    .data - Only available after calling `is_valid()`

    If a `data=` argument is not passed then:

    .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): # many=False后执行的构造方法
        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(BaseSerializer, self).__init__(**kwargs)

    def __new__(cls, *args, **kwargs):
        # We override this method in order to automagically create
        # `ListSerializer` classes instead when `many=True` is set.
        if kwargs.pop('many', False):    # many参数,如果有则执行cls.many_init,没有则执行super(BaseSerializer).__new__
            return cls.many_init(*args, **kwargs)  # many=True,表示对QuerySet进行处理,走该逻辑,
        return super(BaseSerializer, cls).__new__(cls, *args, **kwargs) # many = False ,表示对单独的对象进行处理 ,调用父类field的__new__方法

调用return cls.many_init(*args, **kwargs) 执行的类方法

 @classmethod
    def many_init(cls, *args, **kwargs):
        """
        This method implements the creation of a `ListSerializer` parent
        class when `many=True` is used. You can customize it if you need to
        control which keyword arguments are passed to the parent, and
        which are passed to the child.
        这个方法实现了一个“ListSerializer”父类的创建
		当使用many=True时,初始化。如果需要,可以自定义它
		控制哪些关键字参数传递给父类,以及
		传递给子元素。

        Note that we're over-cautious in passing most arguments to both parent
        and child classes in order to try to cover the general case. If you're
        overriding this method you'll probably want something much simpler, eg:

        @classmethod
        def many_init(cls, *args, **kwargs):
            kwargs['child'] = cls()
            return CustomListSerializer(*args, **kwargs)
        """
        allow_empty = kwargs.pop('allow_empty', None)
        child_serializer = cls(*args, **kwargs)
        list_kwargs = {
            'child': child_serializer,
        }
        if allow_empty is not None:
            list_kwargs['allow_empty'] = allow_empty
        list_kwargs.update({
            key: value for key, value in kwargs.items()
            if key in LIST_SERIALIZER_KWARGS
        })
        meta = getattr(cls, 'Meta', None)
        list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
        return list_serializer_class(*args, **list_kwargs)

下面是field的类,这里不说太多,看看就行

class field:
	 _creation_counter = 0
	
	default_error_messages = {
	 'required': _('This field is required.'),
	 'null': _('This field may not be null.')
	}
	default_validators = []
	default_empty_html = empty
	initial = None
	 def __init__(self, read_only=False, write_only=False,
	                 required=None, default=empty, initial=empty, source=None,
	                 label=None, help_text=None, style=None,
	                 error_messages=None, validators=None, allow_null=False):
	        self._creation_counter = Field._creation_counter
	        Field._creation_counter += 1
	
	        # If `required` is unset, then use `True` unless a default is provided.
	        if required is None:
	            required = default is empty and not read_only
	
	        # Some combinations of keyword arguments do not make sense.
	        assert not (read_only and write_only), NOT_READ_ONLY_WRITE_ONLY
	        assert not (read_only and required), NOT_READ_ONLY_REQUIRED
	        assert not (required and default is not empty), NOT_REQUIRED_DEFAULT
	        assert not (read_only and self.__class__ == Field), USE_READONLYFIELD
	
	 
	
	        if self.default_empty_html is not empty:
	            if default is not empty:
	                self.default_empty_html = default
	
	        if validators is not None:
	            self.validators = list(validators)
	
	        # These are set up by `.bind()` when the field is added to a serializer.
	        self.field_name = None
	        self.parent = None
	
	        # Collect default error message from self and parent classes
	        messages = {}
	        for cls in reversed(self.__class__.__mro__):
	            messages.update(getattr(cls, 'default_error_messages', {}))
	        messages.update(error_messages or {})
	        self.error_messages = messages

我们继续看Serializer类, 执行玩__new__方法接着执行__init__构造方法,此时有根据many值不同执行不同的构造方法,当many=True时候执行cls.many_init方法
下面是BaseSerializer的父类fiedl

class FIeld:
	''''省略一万字'''
    def __new__(cls, *args, **kwargs):
        """
        When a field is instantiated, we store the arguments that were used,
        so that we can present a helpful representation of the object.
		当一个字段被实例化时,我们存储所使用的参数,以便我们可以呈现一个有用的对象表示
        """
        instance = super().__new__(cls)#父类是object
        instance._args = args
        instance._kwargs = kwargs
        return instance

	@classmethod
    def many_init(cls, *args, **kwargs):  # many=True,执行该方法
        """
        This method implements the creation of a `ListSerializer` parent
        class when `many=True` is used. You can customize it if you need to
        control which keyword arguments are passed to the parent, and
        which are passed to the child.
	这个方法实现了一个“ListSerializer”父类的创建
	当使用many=True时,初始化。如果需要,可以自定义它
	控制哪些关键字参数传递给父类,以及
	传递给子元素。

        Note that we're over-cautious in passing most arguments to both parent
        and child classes in order to try to cover the general case. If you're
        overriding this method you'll probably want something much simpler, eg:
	请注意,我们在将大多数争论传递给父母双方时过于谨慎
	和子类,以便涵盖一般情况。如果你
	重写这个方法,你可能会想要一些更简单的东西,例如:

        @classmethod
        def many_init(cls, *args, **kwargs):
            kwargs['child'] = cls()  #传递给CustomListSerializer类
            return CustomListSerializer(*args, **kwargs)
        """
        allow_empty = kwargs.pop('allow_empty', None)
        child_serializer = cls(*args, **kwargs) #实例化
        list_kwargs = {
            'child': child_serializer,
        }
        if allow_empty is not None:
            list_kwargs['allow_empty'] = allow_empty
        list_kwargs.update({
            key: value for key, value in kwargs.items()
            if key in LIST_SERIALIZER_KWARGS
        })
        meta = getattr(cls, 'Meta', None)
        list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
        return list_serializer_class(*args, **list_kwargs)  # 最后使用ListSerializer进行实例化

小结: 对于单独的对象,采用的是Serializer类进行处理,若对象是QuerySet类型(多个对象列表),采用LIstSeriallizer处理,此时我们调用对象的data属性获取结果(示例中这使用的是res.data),实例化后的data属性,寻找时候先从子类找,无该属性就去父类找

class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
	.......
	 @property
	    def data(self):
	        ret = super(Serializer, self).data  # 执行父类data属性
	        return ReturnDict(ret, serializer=self)

父类BaseSerialize的属性方法data源码:

class BaseSerializer(Field):
	@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'):  #从实例中判断_data值
	            if self.instance is not None and not getattr(self, '_errors', None):# 判断有无错误,无错误进行序列化
	                self._data = self.to_representation(self.instance)    # 将instance(QuerySet对象)传入,开始序列化
	            elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
	                self._data = self.to_representation(self.validated_data) 
	             #print(self._data)
			else: 
				self._data = self.get_initial() 
			return self._data

我们在打印下self._data值看看,发现全是我们的数据
在这里插入图片描述
这是我们的self.instance值
在这里插入图片描述

从以上源码中可以看出,通过调用类的self.to_representation方法进行序列化,

 def to_representation(self, instance):
        """
        Object instance -> Dict of primitive datatypes.
        """
        ret = OrderedDict()  #先将instance转化为有序字典
        fields = self._readable_fields

        for field in fields: # 循环定义的字段,这个字段可以是我们自己定义的,也可以是model中的字段
            try:
                attribute = field.get_attribute(instance) #调用字段的get_attribute方法(参数是对象),在示例中可以理解为group.get_attribute(group_obj),
            except SkipField:
                continue

            # We skip `to_representation` for `None` values so that fields do
            # not have to explicitly deal with that case.
            #
            # For related fields with `use_pk_only_optimization` we need to
            # resolve the pk value.
            check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
            if check_for_none is None:
                ret[field.field_name] = None
            else:
                ret[field.field_name] = field.to_representation(attribute)

        return ret

这是to_representation(self, instance):返回的值
在这里插入图片描述

以上源码中,调用field.get_attribute(instance)方法获取每个字段的数据

class Fiels:
  ..........

	 def get_attribute(self, instance):
	 		"""
	        Given the *outgoing* object instance, return the primitive value
	        that should be used for this field.
	        给定*传出的*对象实例,返回原始值
	        """
	        try:
	            #print(self.source_attrs)#['user_type']自定义的字段
	            return get_attribute(instance, self.source_attrs)# 使用他在提取数据 , self.source_attrs:以'.'分割的列表,会被使用为反射获取属性
	        except BuiltinSignatureError as exc:  
	            if self.default is not empty:
	                return self.get_default()
	            if self.allow_null:
	                return None
	            if not self.required:
	                raise SkipField()
	            msg = (
	                'Got {exc_type} when attempting to get a value for field '
	                '`{field}` on serializer `{serializer}`.\nThe serializer '
	                'field might be named incorrectly and not match '
	                'any attribute or key on the `{instance}` instance.\n'
	                'Original exception text was: {exc}.'.format(
	                    exc_type=type(exc).__name__,
	                    field=self.field_name,
	                    serializer=self.parent.__class__.__name__,
	                    instance=instance.__class__.__name__,
	                    exc=exc
	                )
	            )
	            raise type(exc)(msg)

get_attribute(instance, self.source_attrs)的方法

def get_attribute(instance, attrs):
    """
    Similar to Python's built in `getattr(instance, attr)`,
    but takes a list of nested attributes, instead of a single attribute.

    Also accepts either attribute lookup on objects or dictionary lookups.
    """
     
     # attrs:['group','name']或者['get_user_type_display',]
    for attr in attrs:  # 循环列表
        try:
            if isinstance(instance, collections.Mapping): #若果是model字段映射(DRF的内部字段转化),直接调用model类的
                instance = instance[attr]#重新赋值,此时的instance已经改变
            else:
                instance = getattr(instance, attr) #否则,使用反射获取结果,如instance=getattr(userinfo_obj,group)
        except ObjectDoesNotExist:
            return None
        if is_simple_callable(instance): #判断是否是可执行,此时如我们示例中的get_user_type_display,其判断过程在类似下面TIPS中,这里不再做过多说明
            try:
                instance = instance()   #重新赋值,加括号进行执行
            except (AttributeError, KeyError) as exc:
                # If we raised an Attribute or KeyError here it'd get treated
                # as an omitted field in `Field.get_attribute()`. Instead we
                # raise a ValueError to ensure the exception is not masked.
                raise ValueError('Exception raised in callable attribute "{0}"; original exception was: {1}'.format(attr, exc))

    return instance

我们看下instance的值
在这里插入图片描述

以上分析self.source_attrs是一个列表(由source参数按点分割而来),继续回到get_attribute函数,下面是其源码:

调用get_attribute函数,进一步出来,需要分析self.source_attrs参数,下面是self.source_attrs部分源码:

 def bind(self, field_name, parent):
        """
        Initializes the field name and parent for the field instance.
        Called when a field is added to the parent serializer instance.
		初始化字段实例的字段名和父字段。在将字段添加到父序列化器实例时调用。
        """

        # In order to enforce a consistent style, we error if a redundant
        # 'source' argument has been used. For example:
        # my_field = serializer.CharField(source='my_field')
        assert self.source != field_name, (
            "It is redundant to specify `source='%s'` on field '%s' in "
            "serializer '%s', because it is the same as the field name. "
            "Remove the `source` keyword argument." %
            (field_name, self.__class__.__name__, parent.__class__.__name__)
        )

        self.field_name = field_name
        self.parent = parent

        # `self.label` should default to being based on the field name.
        if self.label is None:
            self.label = field_name.replace('_', ' ').capitalize()

        # self.source should default to being the same as the field name.
        if self.source is None:
            self.source = field_name

        # self.source_attrs is a list of attributes that need to be looked up
        # when serializing the instance, or populating the validated data.
        if self.source == '*':
            self.source_attrs = []
        else:
            self.source_attrs = self.source.split('.')
    	#self.source是我们自定义字段传入的source参数,如:gp=serializers.CharField(source='group.name'),sss=serializers.CharField(source='get_user_type_display')
     #最后分割变成['group','name']

4, 无限极分类

直接上代码吧

class AreaInfo(models.Model):
    # id = models.IntegerField(primary_key=True, verbose_name='区域编号')
    name = models.CharField(max_length=255, verbose_name='区域名称',unique=True)
    parent = models.ForeignKey('self', on_delete=models.CASCADE, related_name="children",verbose_name='上级地区编号',null=True,blank=False)
    # manage = models.ForeignKey('auth.User',on_delete=models.CASCADE,verbose_name='唯一管理人')
    manageuser = models.ManyToManyField('auth.User',verbose_name='管理人群',through='AreaManageUser')
    class Meta:
        db_table = 'areainfo'

    def __str__(self):
        return self.name
class AreaSerializer(serializers.ModelSerializer):
    subordinate = serializers.SerializerMethodField()
    manageuser = serializers.SerializerMethodField()
    # imagearea  =  serializers.SerializerMethodField()
    '''
        下面是自定义序列化字段,序列化的属性值由方法来提供,
       方法的名字:固定为 get_属性名,
       方法的参数:self为序列化对象,obj为当前序列化的model的TicketRecord对象,名字随便写
       注意 : 建议自定义序列化字段名不要与model已有的属性名重名,否则会覆盖model已有字段的声明
       注意 : 自定义序列化字段要用SerializerMethodField()作为字段类型
    '''
    class Meta:
        model = AreaInfo
        # fields = "__all__"
        fields = ('id', 'name', 'parent_id','subordinate','imagearea','manageuser')
        depth = 3  # shengd

    def get_subordinate(self, obj, dicts=None):
    '''从字段中调用他本身'''
        return AreaSerializer(obj.children.all(), many=True).data

这里的get_subordinate(self, obj, dicts=None)调用了题他本身
在这里插入图片描述

5,ModelViewSet配合ModelSerializer使用

ModelSerializer自动为我们继承了model中的所以字段,强烈建议我们在开发中使用他
我们 先看ModelViewSet类,他封装了4个类分别对应 get,post ,pat,pach,delete

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass

这里用CreateModelMixin

class CreateModelMixin:
    """
    Create a model instance.
    创建一个模型实例
    """
    def create(self, request, *args, **kwargs):
        # print('*'*100,request.data)
       # 获取相关serializer
        serializer = self.get_serializer(data=request.data)
        
        # 进行serializer的验证
        # raise_exception=True,一旦验证不通过,不再往下执行,直接引发异常
        serializer.is_valid(raise_exception=True)
        
        # 调用perform_create()方法,保存实例
        self.perform_create(serializer)
        
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

我们继续看self.get_serializer(data=request.data)

class GenericAPIView(views.APIView):
......
	def get_serializer(self, *args, **kwargs):
	        """
	        Return the serializer instance that should be used for validating and
	        deserializing input, and for serializing output.
	        Return the serializer instance that should be used for validating and
	        deserializing input, and for serializing output.
	        返回应该用于验证和的序列化器实例
	        反序列化输入和序列化输出。
	        返回应该用于验证和的序列化器实例
	        反序列化输入和序列化输出。
	        """
	        serializer_class = self.get_serializer_class() #序列化类
	        kwargs['context'] = self.get_serializer_context() #给序列化内容添加额外参数
	        return serializer_class(*args, **kwargs)

继续分析 save

class ListSerializer(BaseSerializer):
......
  def save(self, **kwargs):
        assert not hasattr(self, 'save_object'), (
            'Serializer `%s.%s` has old-style version 2 `.save_object()` '
            'that is no longer compatible with REST framework 3. '
            'Use the new-style `.create()` and `.update()` methods instead.' %
            (self.__class__.__module__, self.__class__.__name__)
        )

        assert hasattr(self, '_errors'), (
            'You must call `.is_valid()` before calling `.save()`.'
        )

        assert not self.errors, (
            'You cannot call `.save()` on a serializer with invalid data.'
        )

        # 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)'.'"
        )

        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 = dict(
            list(self.validated_data.items()) +
            list(kwargs.items())
        )

        if self.instance is not None:
            self.instance = self.update(self.instance, validated_data)
            assert self.instance is not None, (
                '`update()` did not return an object instance.'
            )
        else:
            self.instance = self.create(validated_data)
            assert self.instance is not None, (
                '`create()` did not return an object instance.'
            )

        return self.instance

图片传出:https://www.cnblogs.com/pyspark/p/8607801.html
在这里插入图片描述
我们创建一条数据看看,故意出错,验证下逻辑
在这里插入图片描述
这里调用了save下面的 self.create()方法
在这里插入图片描述
我们继续看ModelSerializer.create()方法,

 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:

            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.
        默认实现也不处理嵌套关系。
		如果你想支持可写的嵌套关系,你将需要
		编写一个显式的' .create() '方法。
        """
        raise_errors_on_nested_writes('create', self, validated_data)

        ModelClass = self.Meta.model

        # Remove many-to-many relationships from validated_data.
        从validated_data删除多对多关系。
        # They are not valid arguments to the default `.create()` method,
        它们不是默认' .create() '方法的有效参数,
        # as they require that the instance has already been saved.
        :因为它们要求实例已经被保存。
        info = model_meta.get_field_info(ModelClass)#给定一个模型类,返回一个FieldInfo实例,它是一个namedtuple,包含关于模型中各种字段类型的元数据,包括它们之间关系的信息。
        # print(info)
        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)
        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

这里的validated_data就是我们所接受的数据,这里的ModelClass._default_manager.create(**validated_data)
类似于我们使用的models.objects.create(**validated_data),然后返回instance就是我们所看到是数据
在这里插入图片描述
小结, 总结这个逻辑比较乱一点,
如果有那里出现问题请在下方评论,关于ModelSerializer,还有一些字段名,钩子函数,没有提到
下面的subordinate 就是一个钩子函数了, 函数名是get_files(self,obj),返回值必须是可序列化的,没有一天数据酒调用一次,可写为生成器

class AreaSerializer(serializers.ModelSerializer):
    subordinate = serializers.SerializerMethodField()
    # imagearea  =  serializers.SerializerMethodField()
    '''
        下面是自定义序列化字段,序列化的属性值由方法来提供,
       方法的名字:固定为 get_属性名,
       方法的参数:self为序列化对象,obj为当前序列化的model的TicketRecord对象,名字随便写
       注意 : 建议自定义序列化字段名不要与model已有的属性名重名,否则会覆盖model已有字段的声明
       注意 : 自定义序列化字段要用SerializerMethodField()作为字段类型
    '''
    class Meta:
        model = AreaInfo
        # fields = "__all__"
        fields = ('id', 'name', 'parent_id','subordinate','imagearea','manageuser')
        depth = 3  # shengd

    def get_subordinate(self, obj):
    '''从字段中调用他本身'''
        return AreaSerializer(obj.children.all(), many=True).data

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值