web-dev-qa-db-ja.com

Django RestFramework-ネストされたシリアル化が期待どおりに機能しない

Django-REST-Frameworkを使用しているときに、ネストされたシリアル化されたオブジェクトで選択したフィールドを表示できません。

Addressモデル全体を正しくシリアル化できますが、シリアル化されたAddressにネストされたOutletのいくつかのフィールドのみが必要です。あります

シリアライザーOutletSerializerでフィールドoutlet_addressの値を取得しようとすると、AttributeErrorが発生しました。シリアライザーフィールドの名前が正しくなく、Outletインスタンスの属性またはキーと一致しない可能性があります。元の例外テキストは次のとおりです。「Outlet」オブジェクトには属性「outlet_address」がありません。

api_v1/models.py

class Address(models.Model):
    building = models.CharField(_("shop number, floor & building"), max_length=128)
    street = models.CharField(_("street"), max_length=128, blank=True)
    area = models.ManyToManyField(Area, related_name='address')
    city = models.ForeignKey(City, related_name='address')
    pin_code = models.CharField(_("PIN code"), max_length=6, default="")

    def __unicode__(self):
        return self.building + " " + self.street + " ..."


class Outlet(models.Model):
    name = models.CharField(max_length=100, blank=True)
    chain = models.ForeignKey(Chain, related_name='outlet', blank=True, null=True)
    organization = models.ForeignKey(Organization, blank=True, null=True)
    address = models.OneToOneField(Address, related_name='outlet_address')
    thumbnail = AjaxImageField(upload_to='thumbnails',
                               max_height=200,  #optional
                               max_width=200,  # optional
                               crop=True)  # optional
    date_created = models.DateTimeField(_('date created'), default=timezone.now)

    def __unicode__(self):
        return self.name

api_v1/serializers.py

from rest_framework import serializers
from api_v1.models import Outlet, Address

class AddressSerializer(serializers.ModelSerializer):
    #address_area = AreaSerializer(many=False)

    class Meta:
        model = Address
        fields = ('building', 'street',)
        depth = 3


class OutletSerializer(serializers.ModelSerializer):
    outlet_address = AddressSerializer(many=False)
    #area = serializers.CharField(source='address.area') #multiple levels of nesting?

    class Meta:
        model = Outlet
        fields = ('id', 'name', 'thumbnail', 'outlet_address')
        # fields = ('id', 'name', 'thumbnail', 'address') # this works
        depth = 3

この時点で、アウトレットモデルでoutlet_address属性を見つけることができませんが、シリアライザーで見つけることができるはずです。

シリアライザーOutletSerializerでフィールドoutlet_addressの値を取得しようとすると、AttributeErrorが発生しました。シリアライザーフィールドの名前が正しくなく、Outletインスタンスの属性またはキーと一致しない可能性があります。元の例外テキストは次のとおりです。「Outlet」オブジェクトには属性「outlet_address」がありません。

他の回答で説明されているように、私は試しました:

  1. modelSerializerにmany=を追加する
  2. すべてのモデルにrelated_name=を追加
11
Pranab

これを試して:

from rest_framework import serializers
from api_v1.models import Outlet, Address

class AddressSerializer(serializers.ModelSerializer):

    class Meta:
        model = Address
        fields = ('building', 'street',)
        depth = 3


class OutletSerializer(serializers.ModelSerializer):
    address = AddressSerializer(many=False) # make it address, not outlet_address

    class Meta:
        model = Outlet
        fields = ('id', 'name', 'thumbnail', 'address') # make this address as well, not outlet_address
        depth = 3

上記の変更を行う理由は、Outletモデルに「outlet_address」という属性がなく、「address」という属性があるためです。

同様の問題については、ここを参照してください: Django Restフレームワークはネストされた関係でエラーを返し続けます

12
user2719875

他の回答に加えて、誰かがここに着陸した場合に備えて、以下を追加したいと思います。

ネストされたシリアル化を機能させるには、フィールド名がモデルフィールドに含まれている必要があります。

逆の関係 が必要な場合は、明らかにモデルフィールドにそのようなフィールドはありません。

たとえば、質問の特定のモデルでは、アドレスシリアライザーのすべてのアウトレットを参照する必要がある場合にこれが発生します。

したがって、次のことを行う必要があります。(a)他のモデルの外部キーにrelated_nameを指定する。これは、アウトレットモデルの住所フィールドの関連名であるため、outlet_addressを使用する場所です。

または(b)関連する名前がない場合は、デフォルトのDjango名を使用し、モデル名に_setを追加します(例:outlet_set)。

11
Wtower

モデルアウトレットには、outlet_addressではなく「address」フィールドがあります。シリアライザーを次のように設定することをお勧めします。

class OutletSerializer(serializers.ModelSerializer):
    address = AddressSerializer(many=False)

    class Meta:
        model = Outlet
        fields = ('id', 'name', 'thumbnail', 'address')
        depth = 2
3
Roba