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

一,从表展示主表信息

1,PrimaryKeyRelatedField返回主表的主键值

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

结果
DRF-Serializer-主从表字段数据关联 - 图1

2,StringRelatedField返回主表对应对象的str方法的结果

只用来获取数据

  1. from .models import Interfaces
  2. from projects.models import Projects
  3. from rest_framework import serializers
  4. class InterfaceModelSerializer(serializers.ModelSerializer):
  5. projects = serializers.StringRelatedField()
  6. class Meta:
  7. model = Interfaces
  8. fields = '__all__'

验证结果
DRF-Serializer-主从表字段数据关联 - 图2

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

  • 只用于获取数据
  • slug_field定义需要返回的字段数据 ```python from .models import Interfaces from projects.models import Projects from rest_framework import serializers

class InterfaceModelSerializer(serializers.ModelSerializer):

  1. projects = serializers.SlugRelatedField(slug_field='name', read_only=True)
  2. class Meta:
  3. model = Interfaces
  4. fields = '__all__'
验证结果<br />![](https://cdn.nlark.com/yuque/0/2020/png/1608527/1596886080175-cc5f946d-084a-4df5-889d-0df60bbff0ad.png#align=left&display=inline&height=463&margin=%5Bobject%20Object%5D&originHeight=463&originWidth=697&size=0&status=done&style=none&width=697)
<a name="yEMx4"></a>
## 4,显示主表的详细信息

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

![](https://cdn.nlark.com/yuque/0/2020/png/1608527/1596886178743-71b1fff4-a3e2-4b47-bbfd-e646eec68214.png#align=left&display=inline&height=515&margin=%5Bobject%20Object%5D&originHeight=515&originWidth=1180&size=0&status=done&style=none&width=1180)
```python
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属性中 ```python 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)
# 命名规则为从表模型类名小写_set 
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
        }
    }
验证结果:<br />![](https://cdn.nlark.com/yuque/0/2020/png/1608527/1596886402751-4a017579-1577-48ca-b3a1-3eac49188c6f.png#align=left&display=inline&height=804&margin=%5Bobject%20Object%5D&originHeight=804&originWidth=639&size=0&status=done&style=none&width=639)<br />除了这种方法,也可以使用下面的设置方案

- PrimaryKeyRelatedField
- StringRelatedField  # 展示的结果有多条时,设置many=True
- SlugRelatedField
<a name="kwYp4"></a>
## 2,修改外键字段名称

- 在从表的模型类对象中,给定义的外键添加一个属性 related_name
- 这种方式是上面的那种命名方式的优化,采用之后不用按照之前的命名规则, “从表模型类名小写_set 来进行书写
```python
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属性中 ```python 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)
# 此处就可以不在使用之前的命名规范,直接使用related_name的属性值
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
        }
    }

``` 验证结果:
DRF-Serializer-主从表字段数据关联 - 图3