欢迎来到赛兔子家园

Django restframework 嵌套关系处理

序列化器返回models之间有关联关系数据

在序列化器使用过程中,一般一个序列化器对应一个模型数据。但是因为模型之间会存在外键关联,所以一般在输出数据时不仅要获取当前模型的数据,甚至要其他模型的数据也需要同时返回,这种情况下,我们可以通过序列化器嵌套调用的方式,帮我们把当前模型数据进行转换以外,还可以同时转换外键对应的模型数据。

默认情况下:一对多或者多对多的序列化器嵌套返回多个数据情况。默认情况下,模型经过序列化器的数据转换,对于外键的信息,仅仅把数据库里面的外键ID返回。

models.py

from datetime import datetime

from django.db import models

# Create your models here.


class Student(models.Model):
    """学生信息"""
    name = models.CharField(max_length=100, verbose_name="姓名")
    sex = models.BooleanField(default=1, verbose_name="性别")
    age = models.IntegerField(verbose_name="年龄",help_text="年龄不能小于0")
    classmate = models.CharField(max_length=5, verbose_name="班级编号")
    description = models.TextField(max_length=1000, verbose_name="个性签名")

    class Meta:
        db_table = "to_student"
        verbose_name = "学生"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

    def achievement(self):
        """成绩表"""
        return self.s_achievement.values("course__teacher__name", "course__name", "score")  # 返回全部字段


class Course(models.Model):
    name = models.CharField(max_length=50, verbose_name="课程名称")
    teacher = models.ForeignKey(to="Teacher", on_delete=models.DO_NOTHING, related_name="course",
                                db_constraint=False)  # db_constraint虚拟外键,db_constraint=False关闭物理外键

    class Meta:
        db_table = "sch_course"

    def __str__(self):
        return self.name


class Teacher(models.Model):
    name = models.CharField(max_length=50, verbose_name="姓名")
    sex = models.BooleanField(default=False)

    class Meta:
        db_table = "sch_teacher"

    def __str__(self):
        return self.name


class Achievement(models.Model):
    """成绩"""
    score = models.DecimalField(default=0, max_digits=4, decimal_places=1, verbose_name="成绩")
    student = models.ForeignKey(to="Student", on_delete=models.DO_NOTHING, related_name="s_achievement",
                                db_constraint=False)
    course = models.ForeignKey(to="Course", on_delete=models.DO_NOTHING, related_name="c_achievement",
                               db_constraint=False)
    create_time = models.DateTimeField(auto_created=datetime.now)

    class Meta:
        db_table = "sch_achievement"

    def __str__(self):
        return str(self.score)
方式1:使用序化器嵌套解决关联关系

serializers.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'tian'
__data__ = '2022/9/7 19:08'
# software: PyCharm

from rest_framework import serializers

from apps.web.models import Student, Achievement, Course,Teacher


class CourseModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Course
        fields = ["name"]

class AchievementModelSerializer(serializers.ModelSerializer):
    course = CourseModelSerializer()
    class Meta:
        model = Achievement
        fields = ["id","course","score","create_time"]


class StudentModelSerializer(serializers.ModelSerializer):
    s_achievement = AchievementModelSerializer(many=True)# 定义类属性来实例化关联字段的序化器
    class Meta:
        model = Student
        fields = ["id","name","s_achievement"]
方式2:使用关联属性

serializers.py

from rest_framework import serializers

from apps.web.models import Student, Achievement, Course,Teacher



class AchievementModelSerializer(serializers.ModelSerializer):
    # 使用关联属性
    course_name = serializers.CharField(source="course.name")
    teacher_name = serializers.CharField(source="course.teacher.name")
    class Meta:
        model = Achievement
        fields = ["id","course_name","score","create_time","teacher_name"]


class StudentModelSerializer(serializers.ModelSerializer):
    s_achievement = AchievementModelSerializer(many=True)
    class Meta:
        model = Student
        fields = ["id","name","s_achievement"]


class TeacherModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Teacher
        fields = "__all__"
方式3:depth深度属性
# 方式3 深度属性depth

from rest_framework import serializers

from apps.web.models import Student, Achievement, Course, Teacher


class AchievementModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Achievement
        fields = "__all__"
        # depth = 1 # 自动嵌套1层
        depth = 2 # 自动嵌套2层


class StudentModelSerializer(serializers.ModelSerializer):
    s_achievement = AchievementModelSerializer(many=True)
    class Meta:
        model = Student
        fields = ["id", "name", "s_achievement"]
方式4(常用方法):models中自定义属性方法

serializers.py

from rest_framework import serializers

from apps.web.models import Student


class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = ["id", "name","achievement"] # achievement模型类中自定义的属性方法

models.py

class Student(models.Model):
    """学生信息"""
    name = models.CharField(max_length=100, verbose_name="姓名")
    sex = models.BooleanField(default=1, verbose_name="性别")
    age = models.IntegerField(verbose_name="年龄",help_text="年龄不能小于0")
    classmate = models.CharField(max_length=5, verbose_name="班级编号")
    description = models.TextField(max_length=1000, verbose_name="个性签名")

    class Meta:
        db_table = "to_student"
        verbose_name = "学生"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name
    @property
    def achievement(self): # 自定义方法解决关联关系
        """成绩表"""
        return self.s_achievement.values("course__teacher__name", "course__name", "score")  # 返回全部字段

views.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'tian'
__data__ = '2022/9/7 19:10'
# software: PyCharm

from rest_framework.viewsets import ModelViewSet


from apps.web.serializers import manyserializer
from apps.web.models import Student

class StudentModelViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = manyserializer.StudentModelSerializer

urls.py

from rest_framework.routers import DefaultRouter

from apps.web.views import ,manyview

# 1、实例化路由类
router = DefaultRouter()  # 注册
#  2、给路由去注册视图集
router.register("foreign",manyview.StudentModelViewSet,basename="foreign")

urlpatterns = [] +router.urls

posted on 2022-03-29 23:15  赛兔子  阅读(194)  评论(0编辑  收藏  举报

导航