zoukankan      html  css  js  c++  java
  • DRF框架serializer之主从表字段数据关联

    众所周知,前面我们所有的序列化操作只涉及到一张表,而且是主表,那么在序列化的时候从表怎么展示主表的一些信息呢?主表又怎么展示从表信息呢?

    一、从表展示主表信息

    1.PrimaryKeyRelatedField返回主表的主键值

    from .models import Interfaces
    from projects.models import Projects
    from rest_framework import serializers
    
    
    class InterfaceModelSerializer(serializers.ModelSerializer):
        projects = serializers.PrimaryKeyRelatedField(help_text='tb_projects外键', label='Tb_projects外键', queryset=Projects.objects.all())
    
        class Meta:
            model = Interfaces
            fields = '__all__'

    验证结果:

    2.StringRelatedField返回主表对应对象的__str__方法的结果

    • 注意:只用于获取数据
    from .models import Interfaces
    from projects.models import Projects
    from rest_framework import serializers
    
    
    class InterfaceModelSerializer(serializers.ModelSerializer):
    
        projects = serializers.StringRelatedField()
    
        class Meta:
            model = Interfaces
            fields = '__all__'

    验证结果:

    3.SlugRelatedField返回主表的某一个字段的值

    • 注意:只用于获取数据
    • slug_field定义需要返回的字段数据
    from .models import Interfaces
    from projects.models import Projects
    from rest_framework import serializers
    
    
    class InterfaceModelSerializer(serializers.ModelSerializer):
    
        projects = serializers.SlugRelatedField(slug_field='name', read_only=True)
    
        class Meta:
            model = Interfaces
            fields = '__all__'

    验证结果:

    4.展示主表的详细信息

    直接在从表的序列化器类中定义一个主表的序列化器类,因为外键字段类和序列化器类最终都继承了rest_framework.fields.Field的父类,因此可以将序列化器类创建为一个字段的对象,我们可以看看继承关系图

    from .models import Interfaces
    from projects.models import Projects
    from rest_framework import serializers
    from projects.serializers import ProjectsModelSerializer
    
    
    class InterfaceModelSerializer(serializers.ModelSerializer):
    
        projects = ProjectsModelSerializer(label='所属项目信息', help_text='所属项目信息', read_only=True)
    
        class Meta:
            model = Interfaces
            fields = '__all__'

    一、主表展示从表信息

    1.关联设置

    • 直接在主表的序列化对象中创建从表的序列化器类的对象,并赋值给字段名为“从表模型类名小写_set”的字段名称
    • 将“从表模型类名小写_set”的字符名添加到Meta子类的fields属性中
    from rest_framework import serializers
    from rest_framework import validators
    from .models import Projects
    from interfaces.serializers import InterfaceModelSerializer
    
    
    def name_is_not_contain_x(value):
        if 'X' in value.upper():
            raise serializers.ValidationError("项目名字段name不能包含x的大小写字符")
    
    
    class ProjectsModelSerializer(serializers.ModelSerializer):
    
        email = serializers.EmailField(read_only=True, allow_blank=True, allow_null=True)
        interfaces_set = InterfaceModelSerializer(label='所拥有的从表数据信息', many=True)
    
        class Meta:
            model = Projects
            fields = ('id', 'name', 'leader', 'programmer', 'tester', 'create_time', 'update_time', 'email', 'interfaces_set')
            extra_kwargs = {
                'name': {
                    'max_length': 50,
                    'validators': [validators.UniqueValidator(queryset=Projects.objects.all(), message="项目名字段name必须唯一"),
                                   name_is_not_contain_x]
                },
                'tester': {
                    'max_length': 200
                }
            }

    验证结果:

    除了这种方法,也可以使用以下设置

    • PrimaryKeyRelatedField
    • StringRelatedField  # 展示的结果有多条时,设置many=True
    • SlugRelatedField

    2.修改外键字段名称

    • 在从表的模型类对象中,给定义的外键添加一个属性:related_name
    from django.db import models
    
    
    class Interfaces(models.Model):
        projects = models.ForeignKey(to='projects.Projects', on_delete=models.CASCADE, verbose_name='tb_projects外键', 
                                     help_text='tb_projects外键', related_name='interfaces')
    
        name = models.CharField(verbose_name='接口名称', max_length=200, unique=True, help_text='接口名称')
    
        tester = models.CharField(verbose_name='测试人员', max_length=50, help_text='测试人员')
    
        desc = models.CharField(verbose_name='简要描述', max_length=200, null=True, blank=True, default='', help_text='简要描述')
    
        class Meta:
    
            db_table = 'tb_interfaces'
            verbose_name = '接口信息'
            verbose_name_plural = verbose_name
    • 在主表的序列化器类中,将外键字段名称“从表模型类名小写_set”更改为related_name属性的值
    • 删除以“_set”结尾的外键字段名称,将修改过的外键字段名称添加到Meta子类的fields属性中
    from rest_framework import serializers
    from rest_framework import validators
    from .models import Projects
    from interfaces.serializers import InterfaceModelSerializer
    
    
    def name_is_not_contain_x(value):
        if 'X' in value.upper():
            raise serializers.ValidationError("项目名字段name不能包含x的大小写字符")
    
    
    class ProjectsModelSerializer(serializers.ModelSerializer):
    
        email = serializers.EmailField(read_only=True, allow_blank=True, allow_null=True)
        interfaces = InterfaceModelSerializer(label='所拥有的从表数据信息', many=True)
    
        class Meta:
            model = Projects
            fields = ('id', 'name', 'leader', 'programmer', 'tester', 'create_time', 'update_time', 'email', 'interfaces')
            extra_kwargs = {
                'name': {
                    'max_length': 50,
                    'validators': [validators.UniqueValidator(queryset=Projects.objects.all(), message="项目名字段name必须唯一"),
                                   name_is_not_contain_x]
                },
                'tester': {
                    'max_length': 200
                }
            }

    验证结果:

  • 相关阅读:
    hdu1010 Tempter of the Bone(深搜+剪枝问题)
    08-Objective-C特有语法:@property、@synthesize
    Servlet的Response.setContentLength无效
    Java Future
    android一些若干回调测试
    那些有趣的Webview细节
    androidlog日志之 Klog (StackTraceElement)
    曾几何时遇到的bug(viewpager+fragment)
    Android acache读后感
    11-8 定时器this
  • 原文地址:https://www.cnblogs.com/xiaogongjin/p/13288397.html
Copyright © 2011-2022 走看看