django-rest-frameworkシリアライザーを使用して外部キー値を取得する


83

djangoRESTフレームワークを使用してAPIを作成しています。私は次のモデルを持っています:

class Category(models.Model):
    name = models.CharField(max_length=100)

    def __unicode__(self):
        return self.name


class Item(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, related_name='items')

    def __unicode__(self):
        return self.name

私が行うカテゴリのシリアライザーを作成するには:

class CategorySerializer(serializers.ModelSerializer):
    items = serializers.RelatedField(many=True)

    class Meta:
        model = Category

...そしてこれは私に以下を提供します:

[{'items': [u'Item 1', u'Item 2', u'Item 3'], u'id': 1, 'name': u'Cat 1'},
 {'items': [u'Item 4', u'Item 5', u'Item 6'], u'id': 2, 'name': u'Cat 2'},
 {'items': [u'Item 7', u'Item 8', u'Item 9'], u'id': 3, 'name': u'Cat 3'}]

アイテムシリアライザーから逆を取得するにはどうすればよいですか?

[{u'id': 1, 'name': 'Item 1', 'category_name': u'Cat 1'},
{u'id': 2, 'name': 'Item 2', 'category_name': u'Cat 1'},
{u'id': 3, 'name': 'Item 3', 'category_name': u'Cat 1'},
{u'id': 4, 'name': 'Item 4', 'category_name': u'Cat 2'},
{u'id': 5, 'name': 'Item 5', 'category_name': u'Cat 2'},
{u'id': 6, 'name': 'Item 6', 'category_name': u'Cat 2'},
{u'id': 7, 'name': 'Item 7', 'category_name': u'Cat 3'},
{u'id': 8, 'name': 'Item 8', 'category_name': u'Cat 3'},
{u'id': 9, 'name': 'Item 9', 'category_name': u'Cat 3'}]

残りのフレームワークの逆の関係に関するドキュメントを読みましたが、それは非逆のフィールドと同じ結果のようです。明らかな何かが欠けていますか?

回答:


82

を設定せずに関連フィールドを使用するだけですmany=True

また、という名前の出力が必要ですcategory_nameが、実際のフィールドはcategoryであるため、sourceシリアライザーフィールドで引数を使用する必要があることに注意してください。

以下はあなたが必要とする出力を与えるはずです...

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.RelatedField(source='category', read_only=True)

    class Meta:
        model = Item
        fields = ('id', 'name', 'category_name')

21
カテゴリモデルのすべてのフィールドを取得するのはどうですか?
AJ

12
カテゴリモデルのすべてのフィールドを取得する場合は、カテゴリシリアライザを作成し、category_name = CategorySerliazer()
Faizan Ali 2014

7
これを実行しようとしましたが、エラーが発生します Relational field must provide a 'queryset' argument, or set read_only='True'
ePascoal 2015

または、作成/更新をサポートする場合は、次のようなクエリセット属性category_name = serializers.RelatedField(source='category', queryset=Category.objects.all()) を指定します。
stelios 2016年

1
あなたが取得する場合AssertionError:...、この答えの使用stackoverflow.com/a/44530606/5403449
ジョシュ

82

DRFバージョン3.6.3では、これは私のために働いた

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source='category.name')

    class Meta:
        model = Item
        fields = ('id', 'name', 'category_name')

詳細については、こちらをご覧ください:SerializerFieldsのコア引数


ただし、アイテムモデルのカテゴリフィールドがblank = Trueに設定されている場合はNoneTypeエラーがスローされるため、注意する必要があります
デザートキャメル

29

あなたができるもう一つのことは:

  • Itemカテゴリ名を返すプロパティをモデルに作成し、
  • として公開しReadOnlyFieldます。

モデルは次のようになります。

class Item(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, related_name='items')

    def __unicode__(self):
        return self.name

    @property
    def category_name(self):
        return self.category.name

シリアライザーは次のようになります。シリアcategory_nameライザーは、フィールドに同じ名前を付けることで、モデルプロパティの値を自動的に取得することに注意してください。

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField()

    class Meta:
        model = Item

16

これは私にとってはうまくいきました:

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField(source='category.name')
    class Meta:
        model = Item
        fields = "__all__"

9

2018年8月8日およびDRFバージョン3.8.2で動作しました:

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField(source='category.name')

    class Meta:
        model = Item
        read_only_fields = ('id', 'category_name')
        fields = ('id', 'category_name', 'name',)

Metaread_only_fieldsを使用して、どのフィールドをread_onlyにするかを正確に宣言できます。次にforeign、メタでフィールドを宣言する必要がありますfields(マントラが進むにつれて明示的にする方がよい:zen of python)。


5

簡単な解決策は source='category.name'どこcategory外部キーで、.nameそれは属性です。

from rest_framework.serializers import ModelSerializer, ReadOnlyField
from my_app.models import Item

class ItemSerializer(ModelSerializer):
    category_name = ReadOnlyField(source='category.name')

    class Meta:
        model = Item
        fields = "__all__"

0

ソースモデルを定義する必要がないため、このソリューションの方が優れています。ただし、シリアライザフィールドの名前は外部キーフィールド名と同じである必要があります

class ItemSerializer(serializers.ModelSerializer):
    category = serializers.SlugRelatedField(read_only=True, slug_field='title')

    class Meta:
        model = Item
        fields = ('id', 'name', 'category')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.