Django Rest Framework在创建记录后将字段设置为read_only [英] Django Rest Framework set a field read_only after record is created

查看:384
本文介绍了Django Rest Framework在创建记录后将字段设置为read_only的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Django 2.x Django REST Framework

我有一个使用联系人作为外键的模型

I have a model with contact as a foreign key

class AmountGiven(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
    amount = models.FloatField(help_text='Amount given to the contact')
    given_date = models.DateField(default=timezone.now)
    created = models.DateTimeField(auto_now=True)

和序列化程序,如

class AmountGivenSerializer(serializers.ModelSerializer):
    mode_of_payment = serializers.PrimaryKeyRelatedField(queryset=ModeOfPayment.objects.all())
    contact_detail = ContactSerializer(source='contact', read_only=True)
    contact = serializers.PrimaryKeyRelatedField(queryset=Contact.objects.all())

    class Meta:
        model = AmountGiven
        depth = 1
        fields = (
            'id', 'contact', 'contact_detail', 'amount', 'given_date', 'created'
        )

contact 字段。但是我不希望联系人创建后就对其进行修改。

contact field is required while creating a new record. But I do not want contact to be modified once it is created.

但是当我仅发送金额使用 PUT 方法表示

But when I send only amount with PUT method it says

{
    "contact": [
        "This field is required."
    ]
}

当我使用 PATCH时方法,它可以正常工作,但是如果为 contact 传递其他值,它将更新 contact

And when I use PATCH method, it works fine but if passing some other value for contact, it is updating contact as well.

我想建立联系人字段不需要,同时更新现有记录。即使已通过,也请使用较早的版本,而不要设置新数据。

I want to make contact field not-required while updating existing record. And even if it is passed, use the earlier one instead of setting the new data.


试用2

Trial 2

我尝试将请求中的 contact 字段覆盖为先前存储的值,以防万一如果更改了联系人,或者没有通过联系人,它将保存较早的联系人。

I tried overriding the contact field in the request to the previously stored value so that in case if changed contact is passed or no contact is passed, it will save earlier one.

因此,在视图集中添加函数

So, in the viewset add the function

def update(self, request, *args, **kwargs):
    obj = self.get_object()
    request.data['contact'] = obj.contact_id
    return super().update(request, *args, **kwargs)

但这给出了错误,因为

This QueryDict instance is immutable


推荐答案

使用序列化器的 __ init __ 方法使其在对象更新时读取:

Use __init__ method of serializer to make it read when object is being updated:

class AmountGivenSerializer(serializers.ModelSerializer):  

    def __init__(self, *args, **kwargs):
        """If object is being updated don't allow contact to be changed."""
        super().__init__(*args, **kwargs)
        if self.instance is not None:
            self.fields.get('parent').read_only = True
            # self.fields.pop('parent') # or remove the field


    mode_of_payment = serializers.PrimaryKeyRelatedField(queryset=ModeOfPayment.objects.all())
    contact_detail = ContactSerializer(source='contact', read_only=True)
    contact = serializers.PrimaryKeyRelatedField(queryset=Contact.objects.all())

    class Meta:
        model = AmountGiven
        depth = 1
        fields = (
            'id', 'contact', 'contact_detail', 'amount', 'given_date', 'created'
        )

使用 self.context ['view']。action 不建议使用,因为使用Serializ时它将不起作用超出DRF,例如在常规Django视图中。最好使用 self.instance ,因为它在每种情况下都可以使用。

Using self.context['view'].action is not recommended as it will not work when using the serializer out of DRF, eg. in normal Django views. It's best to use self.instance as it will work in every situation.

这篇关于Django Rest Framework在创建记录后将字段设置为read_only的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆