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