关联序列化器序列化
默认外键序列化
之前的序列化,只是简单的对一张表进行处理,那么如果遇到一对一,多对一,多对多的情况该咋序列化呢,我们来看看
比如现在有两张很常见的关联表,老师表和学生表
-
一个老师可以有一群学生,但是一个学生只能有一个老师
class Teacher(models.Model): name = models.CharField(max_length=30, verbose_name='老师名') age = models.IntegerField(verbose_name='年纪') def __str__(self): return self.name class Student(models.Model): name = models.CharField(max_length=30, verbose_name='学生名') teacher = models.ForeignKey( Teacher, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='关联老师' ) def __str__(self): return self.name
学生表中,包含外键teacher,外键可以通过如下一些方式进行序列化
StringRelated外键序列化
将关联表的__str__
方法作为结果返回,设置read_only代表该字段不进行反序列化校验
class StudentSer(serializers.ModelSerializer): teacher = serializers.StringRelatedField() class Meta: model = Student fields = '__all__'
编写返回一个学生的接口
class StudentDetail(APIView): def get(self, request): id_ = request.query_params.get('id') # 通过 GET 传参获取当前学生 ID try: stu = Student.objects.get(pk=id_) except Student.DoesNotExist: return Response({'error': '查不到结果'}) ser = StudentSer(instance=stu) return Response(ser.data, status=200)
接口返回效果如下
{ "id": 1, "teacher": "张老师", # teacher 表的__str__方法所返回的 "name": "小红" }
SlugRelated外键序列化
使用关联表的指定字段作为结果返回
class StudentSer(serializers.ModelSerializer): teacher = serializers.SlugRelatedField(read_only=True, slug_field='name') class Meta: model = Student fields = '__all__'
效果就很直观了,返回的就是slug_field字段所对应的模型层里这个字段代表的值
{ "id": 1, "teacher": 20, "name": "小红" }
PrimaryKeyRelated外键序列化
将关联表的主键作为结果返回,使用PrimaryKeyRelatedField字段,该字段需要包含queryset或read_only属性
class StudentSer(serializers.ModelSerializer): teacher = serializers.PrimaryKeyRelatedField(read_only=True) class Meta: model = Student fields = '__all__'
返回的数据类似如下效果
{ "id": 1, "teacher": 1, "name": "小红" }
外键自定义序列化方式
自己构建序列化字段, 此时默认的外键不发生改变,新添加序列化字段
class StudentSer(serializers.ModelSerializer): teacher_name = SerializerMethodField(read_only=True) # 为了获取自定义字段,需要实现一个方法, 方法名: get_字段名 def get_teacher_name(self, obj): # obj 代表当前需要序列化的对象, 此时obj就是学生对象 return obj.teacher.name class Meta: model = Student fields = '__all__'
返回的数据类似如下效果
{ "id": 1, "teacher": 1, "teacher_name": '李老师', "name": "小红" }