Подтвердить что ты не робот

Поле идентификатора модели Django Rest Framework в сериализаторе вложенных отношений

Я использую Django Rest Framework, где у меня есть следующие два сериализатора:

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'] не предоставляется, что означает, что я получаю KeyError 'id' - хотя я добавил его явно в поле ServiceSerializer 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) с помощью вложенных сериализаторов?

РЕДАКТИРОВАТЬ no.2

Когда я печатаю из функции обновления serializer, я получаю следующее:

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 потеряются...

РЕДАКТИРОВАТЬ no.3

В соответствии с Django Rest Framework docs Если какое-то поле будет в выходном представлении сериализатора, оно должно быть HiddenField. Однако это требует значения default... Я проверил это и действительно использовал этот HiddenField со значением по умолчанию "решает" проблему - идентификатор находится в validated_data. Проблема в том, что id неверен. Есть ли возможность установить этот id значение объекта, отправленного в сериализатор?

4b9b3361

Ответ 1

Хорошо. Думаю, я нашел ответ после... внимательно прочитав документы:

Таким образом, согласно docs, поле id может быть установлено в ModelField, например:

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

В самом деле, после добавления этой строки поле id присутствует в validated_data:)

Ответ 2

Принятый ответ работает, но излишне усложнен. Вы можете просто изменить поле идентификатора, чтобы он не был доступен только для чтения. Например. что-то вроде этого:

id = serializers.IntegerField(required=False)

Ответ 3

Вы установили id как ReadOnlyField. Поэтому id не отображается в проверенных данных. Просто удалите эту строку:

id = serializers.ReadOnlyField()