web-dev-qa-db-ja.com

Djangoネストされた関係シリアライザのRESTフレームワークモデルIDフィールド

私は次のようにしていますDjango Rest Frameworkには、次の2つのシリアライザーがあります。

_class ServiceSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = ServiceType
        fields = ('id', 'serviceName', 'servicePrice')


class CompanyShortListSerializer(serializers.ModelSerializer):

     services = ServiceSerializer(many=True)

     class Meta:
         model = Company
         fields = ( 'id','name','address','cost_per_patient','cost_per_month','renting_fee','services')
_

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

_class ServiceType(models.Model):
     serviceName = EncryptedCharField(max_length=100, blank=True, verbose_name = "Typ usługi")
     servicePrice = EncryptedFloatField(null=True, blank=True, verbose_name = "Cena usługi", validators = [MinValueValidator(0.1), MaxValueValidator(999)])
     company = models.ForeignKey(Company, related_name = 'services')
_

関連するサービスを変更することで既存のインスタンスを更新したい(たとえば、それらの一部を削除する)。これを達成するために私はこれをやっています:

_def update(self, instance, validated_data):
    # Updates an exisitng Company with several services 
    instance.name = validated_data['name']
    instance.address = validated_data['address']
    instance.cost_per_patient = validated_data['cost_per_patient']
    instance.renting_fee = validated_data['renting_fee']
    services_data = validated_data['services']

    for item in services_data:
        updatedService = ServiceType(
            serviceName = item['serviceName'],
            servicePrice = item['servicePrice'],
            id=item['id'], 
            company=instance)
        updatedService.save()

    return instance
_

私が直面している問題は、_service['id']_フィールドが提供されていないことです。つまり、ServiceSerializeridに明示的に追加しましたが、_KeyError 'id'_を取得します。フィールド。

[〜#〜]編集[〜#〜]

以下は、私が投稿している(Chromeからの)リクエストの例です。

_ { "id":49,"name":"Test 1",
   "address":"Testowa 1",
   "renting_fee":200,
   "cost_per_month":300,
   "cost_per_patient":null,
   "services":[
   {"id":67,"serviceName":"Terapia","servicePrice":100},
   {"id":68,"serviceName":"Terapia par","servicePrice":150},
   {"id":69,"serviceName":"Terapia po angielsku","servicePrice":120}
   ]
 } 
_

ネストされたシリアライザーを使用してオブジェクト(基本的にはServiceSerializer)のIDを取得するにはどうすればよいですか?

EDIT no.2

シリアライザの更新関数から印刷すると、次のようになります。

print(self.data['services'])は私に与えます:

_[
 OrderedDict([('id', 67), ('serviceName', u'Terapia'), ('servicePrice', 100.0)]),
 OrderedDict([('id', 68), ('serviceName', u'Terapia par'), ('servicePrice', 150.0)]),
 OrderedDict([('id', 69), ('serviceName', u'Terapia po angielsku'), ('servicePrice', 120.0)]), 
 OrderedDict([('id', 70), ('serviceName', u'Terapia grupowa'), ('servicePrice', 140.0)])
]
_

ただし、print(services_data)は以下を提供します(基本的に同じですが、IDはありません)。

_[
OrderedDict([(u'serviceName', u'Terapia'), (u'servicePrice', 100.0)]),
OrderedDict([(u'serviceName', u'Terapia par'), (u'servicePrice', 150.0)]),
OrderedDict([(u'serviceName', u'Terapia po angielsku'), (u'servicePrice', 120.0)])
]
_

そして、idsは迷子になります...

EDIT no.3

Django Rest Framework docs によると、特定のフィールドをシリアライザの出力表現に含める場合は、HiddenFieldにする必要があります。ただし、これにはdefault値が必要です...私はそれを確認し、実際にこのHiddenFieldをデフォルト値で使用して問題を「解決」します-IDはvalidated_dataにあります。問題は、idが正しくないことです。このidをシリアライザに送信されるオブジェクトの値に設定する可能性はありますか?

18
user1544500

OK-答えを見つけたと思います...慎重に読んでください the docs :)

したがって the docs によると、idフィールドは次のようにModelFieldに設定できます。

id = serializers.ModelField(model_field=ServiceType()._meta.get_field('id'))

実際、この行を追加した後、idフィールドはvalidated_dataに存在します:)

24
user1544500

受け入れられた答えは機能しますが、不必要に複雑です。 IDフィールドを読み取り専用に変更するだけです。例えば。このような何かが行います:

id = serializers.IntegerField(required=False)
15
Cory

idReadOnlyFieldとして設定しました。そのため、検証済みデータにidは表示されません。この行を削除してください:

id = serializers.ReadOnlyField()
2
ilse2005

より簡単なオプション:

id = serializers.IntegerField(write_only=False)
0
Braden Holt