Django --DRf --- serializer: serializer nesting

Model table:

from django.db import models

# Create your models here.

class StudentModel(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32,verbose_name='姓名')
    age = models.SmallIntegerField(verbose_name='年龄')
    class_mate_f = models.ForeignKey(to='ClassMateModel',on_delete=models.SET_NULL,null=True,
                                     related_name='students',related_query_name='students',db_constraint=False)

class ClassMateModel(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=64,verbose_name='班级名')

class ClassMateDetail(models.Model):
    id = models.AutoField(primary_key=True)
    address = models.CharField(max_length=32,verbose_name='地址')
    class_mate_f = models.ForeignKey(to='ClassMateModel',on_delete=models.CASCADE,null=True,
                                     related_name='detail',related_query_name='detail',db_constraint=False)

class TeacherModel(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32,verbose_name='姓名')
    age = models.SmallIntegerField(verbose_name='年龄')
    phone = models.CharField(max_length=13,verbose_name='手机号码')
    class_mate_f = models.ManyToManyField(to='ClassMateModel',null=True,
                                          related_name='teachers',related_query_name='teachers',db_constraint=False)

#通过其他三张表的related_name 后,ClassMateModel就多了三个虚拟字段:students,teachers,detail

Please add a picture description

1. The side where the foreign key is located

1. Method 1: Obtain the specified field data through source [one-to-many and one-to-one]

1.1, one-to-many foreign key party
序列化器:
class StudentModelSerializer(serializers.ModelSerializer):
    class_mate_pk = serializers.CharField(source='class_mate_f.id')
    class_mate_name = serializers.CharField(source='class_mate_f.name')
    class Meta:
        model = models.StudentModel
        fields = ['id','name','class_mate_pk','age','class_mate_name']
        
 
视图函数:
#学生创建
class StudentGenericAPIView(GenericAPIView):
    authentication_classes = []
    queryset = models.StudentModel.objects.all()
    serializer_class = serializer.StudentModelSerializer
    def get(self,request):
        ser = self.get_serializer(instance = self.get_queryset(),many=True)
        return Response({
    
    'code':200,'data':ser.data})
1.2. Many-to-many foreign key method [not applicable]

2. Method 2: Through foreign key = serialization class () [applicable to all relationships]

2.1, many-to-many: foreign key here

serializer:

class ClassMateForTeacherModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.ClassMateModel
        fields = ['id','name']

class TeacherModelSerializer(serializers.ModelSerializer):
    class_mate_f = ClassMateForTeacherModelSerializer(many=True)
    class Meta:
        model = models.TeacherModel
        fields = ['id','name','age','phone','class_mate_f']

View class:

class TeacherGenericAPIView(GenericAPIView):
    queryset = models.TeacherModel.objects.all()
    serializer_class = serializer.TeacherModelSerializer

    def get(self,request):
        ser = self.get_serializer(instance = self.get_queryset(),many=True)
        return Response({
    
    'code':200,'data':ser.data})
2.2, one-to-many, foreign key side [student table, nested class]
序列化器:
class ClassMateForStudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.ClassMateModel
        fields = ['id','name']

class StudentModelSerializer(serializers.ModelSerializer):
    class_mate_f = ClassMateForStudentModelSerializer(read_only=True)
    class Meta:
        model = models.StudentModel
        fields = ['id','name','class_mate_f','age']
        
        
视图:
class StudentGenericAPIView(GenericAPIView):
    authentication_classes = []
    queryset = models.StudentModel.objects.all()
    serializer_class = serializer.StudentModelSerializer
    def get(self,request):
        ser = self.get_serializer(instance = self.get_queryset(),many=True)
        return Response({
    
    'code':200,'data':ser.data})

3. Method 3: Through depth [applicable to all relationships]

START TABLE – FOREIGN KEY -------------> TABLE 1 - FOREIGN KEY -------------> TABLE 2 - FOREIGN KEY ----- -------->Table 3

In this way, depth=4 will always track the foreign key until there is no foreign key field in the table.

3.1. One-to-many: student table - foreign key -----> class table
#序列化器
class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.StudentModel
        fields = ['id','name','class_mate_f','age']
        depth = 2 #等于表数

#视图 
class StudentGenericAPIView(GenericAPIView):
    authentication_classes = []
    queryset = models.StudentModel.objects.all()
    serializer_class = serializer.StudentModelSerializer
    def get(self,request):
        ser = self.get_serializer(instance = self.get_queryset(),many=True)
        return Response({
    
    'code':200,'data':ser.data})
3.2. Many-to-many: teacher-foreign key------->class
#序列化器
class TeacherModelSerializer(serializers.ModelSerializer):
    # class_mate_f = ClassMateForTeacherModelSerializer(many=True,read_only=True)
    class Meta:
        model = models.TeacherModel
        fields = ['id','name','age','phone','class_mate_f']
        depth =2 #涉及到的表数量
   
#视图
class TeacherGenericAPIView(GenericAPIView):
    queryset = models.TeacherModel.objects.all()
    serializer_class = serializer.TeacherModelSerializer

    def get(self,request):
        ser = self.get_serializer(instance = self.get_queryset(),many=True)
        return Response({
    
    'code':200,'data':ser.data})
        

Two, the party where the foreign key is not [query class as an example]

[Only the way of serializer nesting can be used]

Note: Reverse query, all through reverse query field = serializer (many=True)

In these four tables: ClassMateModel does not have a foreign key field, but the other three tables have ClassMateModel foreign keys,

Through related_name, in the subquery, you can use the set name to cross tables, and you don’t need to use _set when there are multiple query results;

query_related_name When querying joint tables, perform cross-table operations through the set name.

When querying class information, class details, student information, and teacher information are required; the following is realized by serializer nesting

view:

class ClassMateGenericAPIView(GenericAPIView):
    authentication_classes = []
    queryset = models.ClassMateModel.objects.all()
    serializer_class = serializer.ClassMateModelSerializer
    def get(self,request):
        ser = self.get_serializer(instance = self.get_queryset(),many=True)
        return Response({
    
    'code':200,'data':ser.data})

serializer:

#老师
class TeacherForClassMateMdoelserializer(serializers.ModelSerializer):
    class Meta:
        model = models.TeacherModel
        fields = ['id','name','phone']

#班级详情
class ClassDetailForClassMateModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.ClassMateDetail
        fields =['address']

#学生
class StudentForClassMate(serializers.ModelSerializer):
    class Meta:
        model = models.StudentModel
        fields = ['name','age']

#班级
class ClassMateModelSerializer(serializers.ModelSerializer):
    teachers = TeacherForClassMateMdoelserializer(many=True,read_only=True)
    detail = ClassDetailForClassMateModelSerializer(many=True,read_only=True)
    students = StudentForClassMate(many=True,read_only=True)
    class Meta:
        model = models.ClassMateModel
        fields =['id','name','teachers','students','detail']
        extra_kwargs = {
    
    
            'id':{
    
    'read_only':True},
            'teachers':{
    
    'read_only':True},
            'detail':{
    
    'read_only':True},
            'students':{
    
    'read_only':True},
        }

总结
1、通过related_name , ClassMateModel 相当于多了,students、teachers和detail 三个字段。
2、使用这三个字段来接收序列器对象,就可以实现序列化嵌套了。
3、注意,在实例化序列化器时,必须带上many=True 不然会报错。【因为外键不在当前模型类中,所有可能会有多个数据,即使是一对一的关系表,也要加many=true】
4、加上read_only=True ,不参与到反序列化中。如果该序列化器不参与反序列就无须写。

Summary
1. Through related_name, ClassMateModel is equivalent to more, three fields of students, teachers and details.
2. Use these three fields to receive the serializer object, and serialization nesting can be realized.
3. Note that when instantiating the serializer, you must bring many=True, otherwise an error will be reported. [Because the foreign key is not in the current model class, there may be multiple data, even if it is a one-to-one relational table, many=true must be added] 4. Add
read_only=True to not participate in deserialization. If the serializer does not participate in deserialization, there is no need to write.

Guess you like

Origin blog.csdn.net/weixin_46371752/article/details/130310378