将可编辑字段作为 Django-Rest-Framework Serializer 的验证数据方法传递

Posted

技术标签:

【中文标题】将可编辑字段作为 Django-Rest-Framework Serializer 的验证数据方法传递【英文标题】:Passing Editable Fields as validated_data method of Django-Rest-Framework Serializer 【发布时间】:2021-07-21 19:20:29 【问题描述】:

我正在 Django-REST-Framework 中编写联系人服务。 我有一个Contact 模型和一个PhoneNumber 模型,它有一个foreignKey 字段,显示它属于哪个联系人。 这是我的模型:

class ContactModel(models.Model):
    firstname = models.CharField(max_length=50, blank=False)
    lastname = models.CharField(max_length=50, blank=False)

class PhoneNumber(BaseModel):
    country_code = models.CharField(max_length=VERY_SHORT_STRING_SIZE, blank=False)
    phone_number = models.CharField(max_length=SHORT_STRING_SIZE, blank=False, null=False)
    label = models.CharField(max_length=NORMAL_STRING_SIZE, blank=True, default='')
    related_contact = models.ForeignKey(to='ContactModel', on_delete=models.CASCADE)

我想为我的联系人创建一个CRUD api。我有一个ModelViewSet 和一个ModelSerializer。序列化代码如下:

class ContactSerializer(serializers.ModelSerializer):
    phonenumber_set = PhoneSerializer(many=True, required=False)
        class Meta:
            model = ContactModel
            fields = '__all__'

class PhoneSerializer(serializers.ModelSerializer):
    class Meta:
        model = PhoneNumber
        fields = ['id', 'country_code', 'phone_number', 'label']

正如 here 指定的那样,我应该重写 update 和 create 方法,以便更新和创建我的联系人的 PhoneNumbers。

问题是,如果我重写这些函数,我必须像这样使用它们:

class ContactSerializer(serializers.ModelSerializer):
    ...
    def create(self, validated_data):
        # some code for creating both PhoneNumber and Contact


    def update(self, instance, validated_data):
        # some code for updating both PhoneNumber and Contact

不幸的是,'validated_data' 参数不会带来我的 PhoneNumber 对象的 'id',因为 'id' 字段是 AutoFields 并且 AutoFields 在 DRF 中将是只读的(已解释 Here )。

有没有办法让我在我的更新方法中访问我的“id”字段? (有点需要)

谢谢。

【问题讨论】:

【参考方案1】:

只需在update() 方法中循环instance.phonenumber_set.all(),您就可以完全访问这些相关对象。

例如:

def update(self, instance, validated_data):
    for phonenumber in instance.phonenumber_set.all():
        # do what you want with phonenumber, like phonenumber.id

instance 是在您的序列化程序中更新的当前对象,它作为参数传递给update(),如您所见,因此您可以像往常一样访问和执行任何操作。

提示:

最好将related_name添加到related_contact以提高可读性,同时将related_contact更改为contactsrelated_name 用于选择反向关系,就像我们现在一样。

我认为这样做更好:

contacts = models.ForeignKey(to='ContactModel', on_delete=models.CASCADE, related_name='phonenumbers')

所以不要使用phonenumber_set,而是使用phonenumbers 以获得更好的可读性,但_map 的名称仍然有效,see this answer 以获取有关related_name 的更多信息

【讨论】:

不要认为这会有所帮助。我需要一个 PhoneNumbers id,而不是我的实例 id。 抱歉,我以为你问的是对象本身。我已经更新了我的答案,请查看。 非常感谢您的帮助,但我不得不说,很遗憾,这又不是答案。通过使用“instance.phonenumbers_set.all()”,我将获取当前存储在我的联系人数据库中的所有 phone_numbers。我想要的是刚刚从客户端发送的待更新电话号码的传递ID。 好的,现在我知道你的目标了,但是,你能分享你的请求数据吗?通常instance 是要更新的对象,所以你应该看看那里,但让我们看看。

以上是关于将可编辑字段作为 Django-Rest-Framework Serializer 的验证数据方法传递的主要内容,如果未能解决你的问题,请参考以下文章

如何将可编辑的文本和图像添加到threejs

如何将可编辑数据传递给组件?

如何使用 typeorm 将可为空的数据库字段设置为 NULL?

将可为空的 DateTime 字段更新为 null 会导致默认 DateTime 值 (0001-01-01 00:00:00.0000000)

将可编辑添加到引导表

如何将可编辑内容保存到 WebArchive webView?