跳转至

REST framework入坑(3)-序列化

1. 基本查询

数据用例

# Django ORM
class StudentInfo(models.Model):
    name = models.CharField(max_length=20, verbose_name='姓名')
    birthday = models.DateField(verbose_name='生日', null=True)
    money = models.IntegerField(default=0, verbose_name='现金')
    image = models.ImageField(upload_to='studenttest', verbose_name='照片', null=True)

# 序列化器用例
from rest_framework import serializers

class StudentSerializer(serializers.Serializer)
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='姓名', max_length=20)
    birthday = serializers.DateField(label='生日', required=False)
    money = serializers.IntegerField(label='现金', required=False)
    image = serializers.ImageField(label='照片', required=False)
  • 单一对象查询
# 得到一个学生对象
student = StudentInfo.objects.get(id=2)

# 构造序列化器对象
serializer = StudentSerializer(student)

# 获得序列化后的数据
print(serializer.data)
# {'id': 2, 'name': '小明', 'birthday': '1996-07-24', 'money': 36,  'image': None}

序列化器对象通过data属性可以获取序列化后的数据

  • 查询集QuerySet查询
# 得到所有的学生
students = StudentInfo.objects.all()

# 构造序列化器对象
serializers = StudentSerializer(students, many = True)

# 打印输出结果
print(serializers.data)
# [OrderedDict([('id', 1), ('name', '小花'), ('birthday', '1998-03-22'), ('money', 21), ('image', None]), OrderedDict([('id', 2), ('name', '小明'), ('birthday', '1996-07-24'), ('money', 36), ('image', None])]

如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明

2. 关联外键嵌套查询

如果需要序列化的数据中包含有其他关联对象,则对关联对象数据的序列化需要指明

  • 比如:一个学生有外键对应的班级,那这个字段该如何显示?

测试用例

from rest_framework import serializers

# 班级类用例
class ClassInfo(models.Model):
    name = models.CharField(max_length=20, verbose_name='班级名称')
    Info = models.CharField(max_length=20, verbose_name='班级信息')

    class Meta:
        db_table = 'class'
    def __str__(self):
        return self.name

# 班级类序列化器用例
class ClassInfoSerializer(serializers.Serializer)
    name = serializers.CharField(label='班级名称', max_length=20)
    Info = serializers.CharField(label='班级信息', max_length=20)


# 学生类用例
class StudentInfo(models.Model):
    name = models.CharField(max_length=20, verbose_name='姓名')
    birthday = models.DateField(verbose_name='生日', null=True)
    money = models.IntegerField(default=0, verbose_name='现金')
    image = models.ImageField(upload_to='studenttest', verbose_name='照片', null=True)
    class Meta:
        db_table = 'students'
    def __str__(self):
        return self.name

# 学生类序列化器用例
class StudentSerializer(serializers.Serializer)
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='姓名', max_length=20)
    birthday = serializers.DateField(label='生日', required=False)
    money = serializers.IntegerField(label='现金', required=False)
    image = serializers.ImageField(label='照片', required=False)
    #定义外键字段
    hclass = serializers.PrimaryKeyRelatedField(label='班级', read_only=True)
    #hclass = serializers.StringRelatedField(label='班级', read_only=True)
    #hclass = ClassInfoSerializer(label='班级', read_only=True)
  • 1. PrimaryKeyRelatedField: 此字段将被序列化为关联对象的主键
student = StudentInfo.objects.get(id=2)
serializer = StudentSerializer(student)
print(serializer.data)
# {'id': 2, 'name': '小明', 'birthday': '1996-07-24', 'money': 36,  'image': None, 'hclass':2}
  • 2. StringRelatedField: 此字段将被序列化为关联对象的字符串表示方式(即模型类中__str__方法的返回值)
student = StudentInfo.objects.get(id=2)
serializer = StudentSerializer(student)
print(serializer.data)
# {'id': 2, 'name': '小明', 'birthday': '1996-07-24', 'money': 36,  'image': None, 'hclass':'九年级二班'}
  • 3. 使用关联对象的序列化器
student = StudentInfo.objects.get(id=2)

# 使用了自定义的序列化器
serializer = StudentSerializer(student)
print(serializer.data)
# {'id': 2, 'name': '小明', 'birthday': '1996-07-24', 'money': 36,  'image': None, 'hclass':OrderedDict([('id', 2), ('name', '九年级二班'), ('Info', '这里是九年级二班的信息')])}

many参数

如果关联的对象不止一个,比如一个班级会有多个学生,此时关联字段类型的指明仍可使用上述三种方式,只是在声明关联字段时,多补充一个many=True参数即可

# 班级类用例
class ClassInfoSerializer(serializers.Serializer)
    name = serializers.CharField(label='班级名称', max_length=20)
    Info = serializers.CharField(label='班级信息', max_length=20)
    studentinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True)  # 新增

serializer = ClassInfoSerializer(ClassInfo.objects.get(id=2))
print(serializer.data)
# {'id': 2, 'name': '九年级二班', 'info': 'xxxxxx', 'studentinfo_set': [1, 2, 9]} #1, 2, 9代表了字表中与之关联的学生id