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
            }
        }

驗證結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM