传递可编辑字段作为Django-Rest-Framework序列化器的validated_data方法

4
我正在使用Django-REST-Framework编写一个联系人服务。 我有一个Contact模型和一个PhoneNumber模型,其中包含一个外键字段,显示它属于哪个联系人。 以下是我的模型:
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']

正如此处所述,我应该重写update和create方法以更新和创建Contact的电话号码。

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

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中是只读的(这在这里有解释)。
我是否有办法在我的更新方法中访问我的'id'字段?(真的非常需要它)
谢谢。
1个回答

0

只需在您的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')

所以,为了更好的可读性,我们将使用phonenumbers而不是phonenumber_set,但带有_map的名称仍然有效。请参考此答案以获取有关related_name的更多信息。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接