嵌套关系序列化程序中的 Django Rest Framework 模型 Id 字段

Posted

技术标签:

【中文标题】嵌套关系序列化程序中的 Django Rest Framework 模型 Id 字段【英文标题】:Django Rest Framework model Id field in nested relationship serializer 【发布时间】:2016-07-28 04:39:22 【问题描述】:

我正在使用 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
   ]
  

我做错了什么以及如何使用嵌套序列化程序获取对象的 ID(基本上是 ServiceSerializer)?

第 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 迷路了...

第 3 号编辑

根据Django Rest Framework docs,如果某个字段将在序列化器输出表示中,则它应该是HiddenField。然而,这需要一个default 值......我已经检查过了,并且确实使用这个带有默认值的 HiddenField '解决了'问题 - ID 存在于 valid_data 中。问题是id 不正确。是否有可能将此id 设置为发送到序列化程序的对象的值?

【问题讨论】:

【参考方案1】:

好的-我想我在...仔细阅读the docs :) 后找到了答案

所以根据the docs id 字段可以设置为这样的ModelField:

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

确实,在添加这一行之后,id 字段出现在 valid_data 中:)

【讨论】:

【参考方案2】:

接受的答案有效,但不必要地复杂。您可以将 ID 字段更改为非只读字段。例如。这样的事情会做:

id = serializers.IntegerField(required=False)

【讨论】:

【参考方案3】:

您已将id 设置为ReadOnlyField。这就是id 不出现在验证数据中的原因。只需删除此行:

id = serializers.ReadOnlyField()

【讨论】:

不幸的是,删除它后,我仍然从序列化程序中得到 `KeyError 'id' '... :( 您发布的 JSON 看起来如何?您可以将此添加到您的问题中吗? 我添加了来自 Chrome 的示例请求。我希望这就够了吗?【参考方案4】:

更直接的选择:

id = serializers.IntegerField(write_only=False)

【讨论】:

以上是关于嵌套关系序列化程序中的 Django Rest Framework 模型 Id 字段的主要内容,如果未能解决你的问题,请参考以下文章

Django Rest Framework 序列化器作为表单和嵌套关系

Django Rest Framework 中嵌套序列化程序的唯一验证

Django-Rest-Framework 中的序列化程序问题

Django REST Framework 序列化程序中的嵌套注释字段

嵌套序列化程序 django rest 框架中的上下文

Django Rest Framework,如何更新序列化程序中的嵌套值