一、关系模型的序列化-多查1
1.1、模型准备
from django.db import models
# Create your models here.
class Classes(models.Model):
name = models.CharField(max_length=20, verbose_name='班级')
class Student(models.Model):
SEX_CHOICES = ((1,'男')), (2, '女')
name = models.CharField(max_length=20, verbose_name='姓名')
age = models.IntegerField(null=True, blank=True, verbose_name='年龄')
sex = models.IntegerField(choices=SEX_CHOICES, default=1, verbose_name='性别')
classes = models.ForeignKey(Classes, on_delete=models.SET_NULL,null=True,verbose_name='班级')
1.2、迁移模型
python manage.py makemigrations
python manage.py migrate
1.3、初始化数据
insert into t_class (name) values ('Python');
insert into t_class (name) values ('SQL');
insert into t_student(name,age,sex,classes) values ('BaiZhan',18,1,1);
insert into t_student(name,age,sex,classes) values ('SXT',20,2,1);
1.4、serializers
class ClassSerializer(serializers.ModelSerializer):
class Meta:
model = Classes
fields = '__all__'
说明:
只是在StudentSerializer类的meta中 fields 字段中添加了 classes 字段,那么序列化时,显示的只是对应的班级的主键id,如:{"id": 3, "name": "terry", "age": 18, "sex": 1, "classes":1}
如果想序列化对应的班级的信息,那么需要在 StudentSerializer 中,重新指定 classes 字段
class StudentSerializer(serializers.ModelSerializer):
#新增 所属班级 属性
classes = ClassesSerializer()
class Meta:
model = Student
fields = ['id', 'name', 'age', 'sex', 'classes']
-
当前修改后的序列化内容为:{"id": 3, "name": "terry", "age": 18, "sex": 1, "classes": {"id": 1, "name": "\u4e00\u73ed"}}
测试
GET http://127.0.0.1:8000/rest_app/students/
二、关系模型的序列化-1查多
以上只是显示了一对多关系中,关系多方查询1的数据的序列化,下面展示如何序列化1查多方多的数据
models:
class Student(models.Model):
SEX_CHOICES = ((1,'男')), (2, '女')
name = models.CharField(max_length=20, verbose_name='姓名')
age = models.IntegerField(null=True, blank=True, verbose_name='年龄')
sex = models.IntegerField(choices=SEX_CHOICES, default=1, verbose_name='性别')
# 必须增加属性 related_name='students'
classes = models.ForeignKey(Classes, related_name='students', null=True, on_delete=models.SET_NULL, verbose_name='班级')
serializers:
from rest_framework import serializers
from .models import Classes, Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ['id','name','age','sex']
class Class2Serializer(serializers.ModelSerializer):
# 通过related_name反向查询的字段,创建序列化器对象
students = StudentSerializer(many=True,read_only=True)
class Meta:
model = Classes
fields = ['id','name','students']
注意
StudentSerializer 必须在 ClassesSerializer 上面
urls:
path('classes/<int:pk>/', views.classes_detail),
views:
def classes_detail(request, pk):
try:
classes = Classes.objects.get(pk=pk)
except Classes.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'GET':
serializer = ClassesSerializer(classes)
return JsonResponse(serializer.data)
else:
# 其他情况暂不处理
return HttpResponse(status=503)
测试
GET http://127.0.0.1:8000/rest_app/classes/1/
三、手动处理关系字段
由于serializers类的引用关系的原因,serializers类中能只能有1方引入另1方,不如互相引入
如果业务需求,需要2个关系字段都序列化,那么就需要使用到 serializers.RelatedField 类,手动处理关系字段
serializers:
from rest_framework import serializers
from .models import Classes, Student
class StudentRelateFiled(serializers.RelatedField):
# 重写to_representation方法,将外键关联的对象转换为指定的格式
def to_representation(self, value):
return {'id':value.id,'name':value.name,'age':value.age}
class ClassSerializer(serializers.ModelSerializer):
students = StudentRelateFiled(many=True,read_only=True)
class Meta:
model = Classes
fields = ['id','name','students']
class StudentSerializer(serializers.ModelSerializer):
# 通过外键关联的类,创建序列化器对象
classes = ClassSerializer()
class Meta:
model = Student
fields = ['id','name','age','sex','classes']
注意事项
- 上面3个类的先后顺序不能错
测试:
GET http://127.0.0.1:8000/rest_app/classes2/1/