Django Rest Framework Serializer关系:如何获取父级序列化器中所有子对象的列表?

时间:2015-11-22 09:15:03

标签: python django serialization django-rest-framework

我是DRF的新手,刚刚开始构建API。我有两个模型,一个子模型连接到具有外键的父模型。这是我所拥有的模型的简化版本:

class Parent(models.Model):
    name = models.CharField(max_length=50)


class Child(models.Model):
    parent = models.ForeignKey(Parent)
    child_name = models.CharField(max_length=80)

要创建序列化程序,我按照DRF Serializer Relations进行了操作,并按以下方式创建了它们:

class ChildSerializer(serializers.HyperlinkedModelSerializer):

    parent_id = serializers.PrimaryKeyRelatedField(queryset=Parent.objects.all(),source='parent.id')

    class Meta:
        model = Child
        fields = ('url','id','child_name','parent_id')

    def create(self, validated_data):
        subject = Child.objects.create(parent=validated_data['parent']['id'], child_name=validated_data['child_name'])

        return child


class ParentSerializer(serializers.HyperlinkedModelSerializer):
    children = ChildSerializer(many=True, read_only=True)
    class Meta:
        model = Course
        fields = ('url','id','name','children')

我正在尝试获取父级序列化程序中所有子项的列表。我想要的是能够得到这样的回应:

{
    'url': 'https://dummyapidomain.com/parents/1/',  
    'id': '1',
    'name': 'Dummy Parent Name',
    'cildren': [
        {'id': 1, 'child_name': 'Dummy Children I'},
        {'id': 2, 'child_name': 'Dummy Children II'},
        {'id': 3, 'child_name': 'Dummy Children III'},
        ...
    ],
}

由于父模型but it is the suggested way to do it in the documentation中父级和子级之间没有链接,并且它不起作用,我没想到这会起作用。

我收到以下错误消息:

Got AttributeError when attempting to get a value for field `children` on serializer `ParentSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Parent` instance.
Original exception text was: 'Parent' object has no attribute 'children'.

我认为这是完全合理的,但我无法理解我在这里缺少的东西。

如何获取父级序列化程序中所有子项的列表?

2 个答案:

答案 0 :(得分:14)

我认为您的问题是您忘记为您的儿童模型添加 related_name 。我会有这样的模型:

class Parent(models.Model):
    name = models.CharField(max_length=50)

class Child(models.Model):
    parent = models.ForeignKey(Parent, related_name='children')  # <--- Add related_name
    child_name = models.CharField(max_length=80)

我认为通过这种改变,你将解决你得到的错误

答案 1 :(得分:11)

您可以通过两种方式实现此目的:

  1. SerializerMethodField: 你的代码变成了这样:

    class ParentSerializer(serializers.ModelSerializer):
    
         children_list = serializers.SerializerMethodField('_get_children')
    
         def _get_children(self, obj):
             serializer = ChildSerializer(obj.child_list(), many=True)
             return serializer.data
    
        class Meta:
            model = Course
            fields = ('url','id','name','children_list')
    
  2. 每个字段都可以是模型或方法的属性,因此您可以在Parent模型中定义get_children_list方法,然后在ParentSerializer的字段列表中调用它:

    class ParentSerializer(serializers.ModelSerializer):
    
        class Meta:
             model = Course
             fields = ('url','id','name','get_children_list')
    
  3. 注意:您需要在此方案中继承serializers.ModelSerializer