定義序列化器,通常是拿模型類的代碼過來修改一下。但是如果遇到有關聯屬性的時候,應該怎么寫呢?
假設有兩個模型類,一個是員工,一個是部門。部門與員工是一對多關系。那么在定義序列器的時候怎么寫關聯屬性的語句呢?
先把沒有涉及關聯屬性的字段寫成序列化器:
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()刪掉!