web-dev-qa-db-ja.com

Django Rest Frameworkシリアライザの関係:親のシリアライザ内のすべての子オブジェクトのリストを取得する方法は?

DRFは初めてで、APIの構築を開始したばかりです。私は2つのモデルを持っています。子モデルは、外部キーで親モデルに接続されています。ここに私が持っているモデルの簡略版があります:

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'},
        ...
    ],
}

ParentモデルにはParentとChildの間にリンクがないため、これが機能するとは期待していませんでした ただし、ドキュメントで推奨される方法です 。機能しませんでした。

次のエラーメッセージが表示されます。

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'.

それは完全に合理的だと思いますが、ここで何が欠けているのか理解できませんでした。

親のシリアライザのすべての子のリストを取得するにはどうすればよいですか?

22
hnroot

あなたの問題は、子供モデルに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)

そして、私はこの変更であなたが得るエラーを解決すると思います

18
AlvaroAV

これは2つの方法で実装できます。

  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')
    

注:このシナリオでは、serializers.ModelSerializerから継承する必要があります

13
Moe Far