没啥说的,挺基础的东西.

  1. class Flow(models.Model):
  2. flow_name = models.CharField(man_length=250)
  3. class Stage(models.Model):
  4. stage_name = models.CharField(man_length=250)
  5. flow = models.ForeignKey(Flow,on_delete=models.CASCADE,related_name='stages')
  6. class Task(models.Model):
  7. task_name = models.CharField(max_length=250)
  8. stage = models.ForeignKey(Stage,on_delete=models.CASCADE,related_name='tasks')
  9. def __str__(self):
  10. return self.task_name
  1. class TaskSerializer(serializers.ModelSerializer)
  2. class Meta:
  3. model = Task
  4. fields = '__all__'

这种情况下,serializer.data中的task的stage属性是对应的id值

PrimaryKeyRelatedField

  1. class StageSerializer(serializers.ModelSerializer)
  2. class Meta:
  3. model = Stage
  4. fields = '__all__'

这样是不会返回task相关信息的.

  1. class StageSerializer(serializers.ModelSerializer)
  2. tasks = serializers.PrimaryKeyRelatedField(many=True)
  3. class Meta:
  4. model = Stage
  5. fields = '__all__'

这样返回数据中的tasks就是一个id列表了.注意,字段名必须与related_name相同(如果没设置related_name,就是类名小写加_set.本例中也就是task_set)

  1. class StageSerializer(serializers.ModelSerializer)
  2. owned_tasks = serializers.PrimaryKeyRelatedField(source='tasks',many=True) #自定义关系来源
  3. class Meta:
  4. model = Stage
  5. fields = '__all__'
  6. class TaskSerializer(serializers.ModelSerializer)
  7. flow = serializers.PrimaryKeyRelatedField(source='stage.flow',many=True) # 点语法来定义多个关系.
  8. class Meta:
  9. model = Task
  10. fields = '__all__'

添加source字段,来自定义关系来源.支持点语法.

StringRelatedField

如果前端是想展示,那么给出id就不太合适了.可以先用万能的SerializerMethodField实现一版

  1. class StageSerializer(serializers.ModelSerializer)
  2. tasks = serializers.SerializerMethodField(many=True)
  3. class Meta:
  4. model = Stage
  5. fields = '__all__'
  6. def get_tasks(self,instance):
  7. return [task.task_name for task in instance.tasks]

同样的,使用StringRelatedField也能实现

  1. class StageSerializer(serializers.ModelSerializer)
  2. tasks = serializers.StringRelatedField(many=True)
  3. class Meta:
  4. model = Stage
  5. fields = '__all__'

注意StringRelatedField最终返回的是模型类的str方法的返回值.

使用StringRelatedField的好处.

曾经,我一直使用万能的SerializerMethodField.来序列化用户的用户名,返回值是user.nickname
后来产品说重名的员工很难分清楚,要改成user.nickname(user.username).于是我东一处西一处改了很多地方,还是有漏掉的.
再后来产品说,领导发话了,他不知道手下人的账户,要再加上部门信息.愤怒之后冷静下来的我深刻的懂得了封装的重要性.如果使用了StringRelatedField,那么永远都只要改一处(也就是user模型的Str方法.)就好了.