美文网首页
15、Django_rest framework_序列化器之自定

15、Django_rest framework_序列化器之自定

作者: 猪儿打滚 | 来源:发表于2019-12-07 15:36 被阅读0次
    一、外键序列化字段PrimaryKeyRelatedField

    首先说明下当前的两个model类的关系:projectinterface的主表,也就是一个project有多个interface
    在对子表进行序列化时,会默认产生一个关联主表模型类的外键字段PrimaryKeyRelatedField

    • 首先对interface模型创建序列化器
    from rest_framework import serializers
    from interfaces.models import Interfaces
    
    class InterfaceModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = Interfaces
            fields = '__all__'
    
    • 从下面查看序列化的结果可以看出,序列化器会使数据库模型中的外键字段,默认产生PrimaryKeyRelatedField外键序列化字段
    >>> from interfaces.serializer import InterfacesSerializer
    >>> InterfacesSerializer()
    # 下面是结果
    InterfacesSerializer():
        id = IntegerField(help_text='id主键', label='Id主键', read_only=True)
        create_time = DateTimeField(help_text='创建时间', label='创建时间', read_only=True)
        update_time = DateTimeField(help_text='更新时间', label='更新时间', read_only=True)
        name = CharField(help_text='接口名称', label='接口名称', max_length=100, validators=[<UniqueValidator(queryset=Interfaces.objects.all())>])
        tester = CharField(help_text='测试人员', label='测试人员', max_length=100)
        desc = CharField(allow_blank=True, allow_null=True, help_text='接口描述', label='接口描述', max_length=500, required=False)
        project = PrimaryKeyRelatedField(help_text='所属项目', queryset=Projects.objects.all())
    
    • 并且,该外键序列化字段输出的值,默认是对应的记录的外键ID值(比如这里查询id=1的interface的信息,project外键输出的就是该interface对应的project信息的ID值)
    >>> from interfaces.models import Interfaces
    >>> one = Interfaces.objects.get(id=1)
    >>> one
    <Interfaces: 项目1 - 接口1>
    >>> serialzer = InterfacesSerializer(one)
    >>> serialzer
    InterfacesSerializer(<Interfaces: 项目1 - 接口1>):
        id = IntegerField(help_text='id主键', label='Id主键', read_only=True)
        create_time = DateTimeField(help_text='创建时间', label='创建时间', read_only=True)
        update_time = DateTimeField(help_text='更新时间', label='更新时间', read_only=True)
        name = CharField(help_text='接口名称', label='接口名称', max_length=100, validators=[<UniqueValidator(queryset=Interfaces.objects.all())>])
        tester = CharField(help_text='测试人员', label='测试人员', max_length=100)
        desc = CharField(allow_blank=True, allow_null=True, help_text='接口描述', label='接口描述', max_length=500, required=False)
        project = PrimaryKeyRelatedField(help_text='所属项目', queryset=Projects.objects.all())
    >>> serialzer.data
    # 结果
    {'id': 1, 'create_time': '2020-07-15T18:31:00+08:00', 'update_time': '2020-07-15T18:32:01.070581+08:00', 'name': '项目1 - 接口1', 'tester': 'test1', 'desc': '这是项目1 - 接口1', 'project': 1}
    
    
    二、外键字段序列化为关联模型对象的__str__方法:StringRelatedField

    续上面,如果想要默认输出的是projectname,那么就要用到StringRelatedFiled字段。
    StringRelatedFiled:此字段将会被序列化为关联对象的字符串表达形式(__str__方法)

    • 1.首先重写models.py中的project类,重写它的__str__方法,让它返回name
    def __str__(self):
        return self.name
    
    • 2.然后在InterfaceModelSerializer序列化类,用serializers.StringRelatedFiled来定义projcet这个外键字段,这样它就会去调用上一步骤中,project模型类的__str__方法,从而返回projectname
    class InterfaceModelSerializer(serializers.ModelSerializer):
        # StringRelatedFiled,此字段将会被序列化为关联对象的字符串表达形式(__str__方法)
        project = serializers.StringRelatedFiled(label='所属项目名称',read_only=True)
        class Meta:
            model = Interfaces
            fields = '__all__'
    
    • 结果:
    >>> from interfaces.serializer import InterfacesSerializer
    >>> from interfaces.models import Interfaces
    >>> one = Interfaces.objects.get(id=1)
    >>> serialzer = InterfacesSerializer(one)
    >>> serialzer.data
    {'id': 1, 'project': '项目一', 'create_time': '2020-07-15T18:31:00+08:00', 'update_time': '2020-07-15T18:32:01.070581+08:00', 'name': '项目1 - 接口1', 'tester': 'test1', 'desc': '这是项目1 - 接口1'}
    
    三、外键字段序列化为关联模型对象的指定字段:SlugRelatedField

    此时想要得到关联project的描述desc字段的值,那么就使用serializers.SlugRelatedField
    serializers.SlugRelatedField:此字段将会被序列化为关联对象的指定字段的值

    • InterfaceModelSerializer序列化类,用serializers.SlugRelatedField来定义projcet这个外键字段,这样它就会返回project的指定字段值
    • 注意:如果指定的外键字段,只需序列化输出,则需指定参数read_only=True;如果也需要反序列化输入,那么需传递一个queryset来进行校验所传入的值:queryset=xxx
    class InterfaceModelSerializer(serializers.ModelSerializer):
        # SlugRelatedField,此字段将会被序列化为关联对象的指定字段的值
        project = serializers.StringRelatedFiled(slug_field='leader',read_only=True)
    
        class Meta:
            model = Interfaces
            fields = '__all__'
    
    • 结果:
    >>> from interfaces.serializer import InterfacesSerializer
    >>> from interfaces.models import Interfaces
    >>> one = Interfaces.objects.get(id=1)
    >>> serialzer = InterfacesSerializer(one)
    >>> serialzer.data
    # 结果,第二个字段
    {'id': 1, 'project': 'leader1', 'create_time': '2020-07-15T18:31:00+08:00', 'update_time': '2020-07-15T18:32:01.070581+08:00', 'name': '项目1 - 接口1', 'tester': 'test1', 'desc': '这是项目1 - 接口1'}
    
    
    四、外键字段序列化为关联模型对象的序列化器

    想要通过外键字段,得到关联模型对象的序列化器

    • 首先在在InterfaceModelSerializer序列化类的py文件,导入project的序列化类,然后再用这个序列化类定义project字段:
    from projects.serializer import ProjectSerializer
    project = ProjectSerializer(label='所属项目', read_only=True)
    
    • 结果:
    one_interface = Interfaces.objects.get(id=1)
    print(one_interface )
    ### 下面是结果
    >>> from interfaces.serializer import InterfacesSerializer
    >>> from interfaces.models import Interfaces
    >>> one = Interfaces.objects.get(id=1)
    >>> serialzer = InterfacesSerializer(one)
    >>> serialzer.data
    {'id': 1, 'project': OrderedDict([('id', 1), ('create_time', '2020-07-15T18:28:00+08:00'), ('update_time', '2020-07-15T18:29:38.245015+08:00'), ('name', '项目一'), ('tester', 'test1'), ('leader', 'leader1'), ('programmer', 'programmer1'), ('publish_app', 'app1'), ('desc', '第一个项目')]), 'create_time': '2020-07-15T18:31:00+08:00', 'update_time': '2020-07-15T18:32:01.070581+08:00', 'name': '项目1 - 接口1', 'tester': 'test1', 'desc': '这是项目1 - 接口1'}
    
    五、反向指定序列化字段[子表模型类名小写_set]

    从上面可以知道,在对子表进行序列化时,会默认产生一个关联主表模型类的外键字段PrimaryKeyRelatedField
    但是如果对主表进行序列化的时候,并不会默认产生关联子表模型类的字段(比如查询一个id=1的project的信息,并不会默认查询该project的interface的信息)
    此时,我们可以手动指定添加这个关联字段。
    比如,我想要在查询一个project的同时,得到该projcet的所有interface信息

    • project类的序列化器中添加(变量名需要是子表模型类名小写_set,因为要得到其关联所有的interface信息,所以需要传参many=True)
    ## 变量名需要是子表模型类名小写_set,并且传参many=True
    interfeces_set = serializers.StringRelatedField(many=True)
    
    • 然后进行序列化并查看
    from projects.serializer import ProjectModelSerializer from projects.models import Projects
    p = Projects.objects.get(id=1)
    ProjectModelSerializer(p).data
    
    • 结果(该projecet只有一个interface)
    {'id': 1, 'name': '项目一', 'interfaces_set': ['Interfaces object (1)', 'Interfaces object (2)'], 'programer': 'lzl',  'desc': '我是项目一的描述'}
    
    • 如果在字表model中,定义了related_name这个字段,那么反向指定序列化字段的值也改变。
      比如说,修改interfaces/models.py
    class Interfaces(BaseModel):
        ...
        # related_name='interfaces',则反向指定序列化字段的值也为interfaces
        project = models.ForeignKey('projects.Projects', on_delete=models.CASCADE, related_name='interfaces', help_text='所属项目') 
      ...
    

    那么,上面例子的interfeces_set应该改成interfaces

    相关文章

      网友评论

          本文标题:15、Django_rest framework_序列化器之自定

          本文链接:https://www.haomeiwen.com/subject/vznlwctx.html