定义序列化器,通常是拿模型类的代码过来修改一下。但是如果遇到有关联属性的时候,应该怎么写呢?
假设有两个模型类,一个是员工,一个是部门。部门与员工是一对多关系。那么在定义序列器的时候怎么写关联属性的语句呢?
先把没有涉及关联属性的字段写成序列化器:
from rest_framework import serializers class DepartmentSerializer(serializers.Serializer): """部门序列化器类""" id = serializers.IntegerField(read_only=True) name = serializers.CharField(max_length=20) create_date = serializers.DateField()class EmployeeSerializer(serializers.Serializer): """员工序列化器""" choices_gender = ( (0, '男'), (1, '女'), ) name = serializers.CharField(max_length=20) age = serializers.IntegerField() gender = serializers.ChoiceField(default=0, choices=choices_gender) salary = serializers.DecimalField(max_digits=8, decimal_places=2) comment = serializers.CharField(max_length=300) hire_date = serializers.DateField()
-
一对多关系中,多的那方的序列化器关联属性的写法:
如果我要对员工对象序列化时有这样的效果:
# 第一种效果
{
"name": "赵小一",
...,
"department": 1, # 第1种:PrimaryKeyRelatedField
}
# 第二种效果
{
"name": "赵小一",
...,
"department": "研发部", # 第2种:StringRelatedField
}
# 第三种效果
{
"name": "赵小一",
...,
"department": { # 第3种:DepartmentSerializer
"id": 1,
"name": "研发部",
"create_date": "2018-1-1"
}
}
员工序列化器的定义如下:
class EmployeeSerializer(serializers.Serializer): """员工序列化器""" choices_gender = ( (0, '男'), (1, '女'), ) name = serializers.CharField(max_length=20) age = serializers.IntegerField() gender = serializers.ChoiceField(default=0, choices=choices_gender) salary = serializers.DecimalField(max_digits=8, decimal_places=2) comment = serializers.CharField(max_length=300) hire_date = serializers.DateField() # 定义序列化器时关联属性的设置 # 1.1 返回关联属性的主键,设置属性为read_only=True表示修改时,即使传过来的员工信息有部门的id,也不做修改,保留原始的值! department = serializers.PrimaryKeyRelatedField(read_only=True) # 1.2 返回关联属性的主键,设置属性为查询集,表示修改时,当你要修改部门时,如果查询集有,可以修改,如果没有,不可以修改! department = serializers.PrimaryKeyRelatedField(queryset=Department.objects.all()) # 2 返回关联属性的类的__str__方法的值。如果我们想要返回部门的名称,可以在model里面增加__str__方法返回部门名称 department = serializers.StringRelatedField() # 3 返回关联属性的所有属性值时,可以这样写: department = DepartmentSerializer()
-
一对多关系中,一的那方的序列化器关联属性的写法:(多对多关系的两边都可以这样写)
部门序列化器的定义如下:
class DepartmentSerializer(serializers.Serializer): """部门序列化器类""" id = serializers.IntegerField(read_only=True) name = serializers.CharField(max_length=20) create_date = serializers.DateField() is_delete = serializers.BooleanField(default=False) # 返回关联属性的主键,因为有多个,所以必须加上many=True employee_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True) # 返回关联属性的类的__str__方法的值。如果我们想要返回员工的名字,可以在model里面增加__str__方法返回员工的名字。 employee_set = serializers.StringRelatedField(many=True) # 返回关联属性的所有属性值 employee_set = EmpSerializer(many=True)
注意:因为一的这方序列化时会出现多条关联属性,所以必须加上many=True。
-
一个小小的坑
如果在一个文件中,定义了员工和部门的序列化器,并且,两个序列化器都返回关联属性的所有属性值时:
部门序列化器有这句语句:
employee = EmployeeSerializer(many = True)
员工序列化器有这句语句:
department = DepartmentSerializer()
此时会出现相互引用的情况,导致出错!
解决办法:
在部门序列化器前再加多一个员工序列化器,并且把department = DepartmentSerializer()删掉!