1. ホーム
  2. django

[解決済み] Django rest フレームワークのネストされた自己参照オブジェクト

2022-11-20 22:22:15

質問

以下のようなモデルを持っています。

class Category(models.Model):
    parentCategory = models.ForeignKey('self', blank=True, null=True, related_name='subcategories')
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=500)

シリアライザーを使って、全カテゴリーのフラットなjson表現を得ることができました。

class CategorySerializer(serializers.HyperlinkedModelSerializer):
    parentCategory = serializers.PrimaryKeyRelatedField()
    subcategories = serializers.ManyRelatedField()

    class Meta:
        model = Category
        fields = ('parentCategory', 'name', 'description', 'subcategories')

今私がしたいことは、サブカテゴリのリストが、そのIDの代わりにサブカテゴリのインラインjson表現を持つようにすることです。どのように私はdjango-rest-frameworkでそれを行うのでしょうか?私はドキュメントでそれを見つけようとしましたが、それは不完全なようです。

どのように解決するのですか?

ManyRelatedFieldを使う代わりに、ネストされたシリアライザをフィールドとして使います。

class SubCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('name', 'description')

class CategorySerializer(serializers.ModelSerializer):
    parentCategory = serializers.PrimaryKeyRelatedField()
    subcategories = serializers.SubCategorySerializer()

    class Meta:
        model = Category
        fields = ('parentCategory', 'name', 'description', 'subcategories')

もし、任意にネストされたフィールドを扱いたい場合は デフォルトのフィールドをカスタマイズする の部分を見てください。 現在、シリアライザーをそれ自身のフィールドとして直接宣言することはできませんが、これらのメソッドを使用して、デフォルトで使用されるフィールドをオーバーライドすることができます。

class CategorySerializer(serializers.ModelSerializer):
    parentCategory = serializers.PrimaryKeyRelatedField()

    class Meta:
        model = Category
        fields = ('parentCategory', 'name', 'description', 'subcategories')

        def get_related_field(self, model_field):
            # Handles initializing the `subcategories` field
            return CategorySerializer()


実は、ご指摘の通り、上記は全く正しいものではありません。 これは少しハックですが、シリアライザがすでに宣言された後にフィールドを追加してみてはいかがでしょうか。

class CategorySerializer(serializers.ModelSerializer):
    parentCategory = serializers.PrimaryKeyRelatedField()

    class Meta:
        model = Category
        fields = ('parentCategory', 'name', 'description', 'subcategories')

CategorySerializer.base_fields['subcategories'] = CategorySerializer()

再帰的な関係を宣言する仕組みは、追加する必要があるものです。


編集 : この種のユースケースに特化したサードパーティのパッケージが利用できるようになったことに注意してください。参照 djangorestframework-recursive .