代码之家  ›  专栏  ›  技术社区  ›  Anuj TBE

Django Rest Framework仅在创建记录后将字段设置为read

  •  0
  • Anuj TBE  · 技术社区  · 6 年前

    我在用 Django 2.x Django REST Framework .

    我有一个模特 contact 作为外键

    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'
            )
    

    接触 创建新记录时需要字段。但我不想 接触 一旦创建就要修改。

    但是当我只发送 amount 具有 PUT 上面说的方法

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

    当我使用 PATCH 方法,它工作正常,但如果传递其他值 接触 ,正在更新 也。

    我想做 接触 领域 not-required 更新现有记录时。即使它被传递了,也要使用前面的那个,而不是设置新的数据。

    试验2

    我试图超越 接触 请求中的字段,以便在更改时 接触 是否通过 接触

    因此,在视图集中添加

    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
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Vaibhav Vishal    6 年前

    使用 __init__ 在更新对象时使其读取的序列化程序的方法:

    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 不建议使用,因为在DRF外使用序列化程序(例如在普通Django视图中)时它将不起作用。最好是用 self.instance 因为它在任何情况下都会起作用。

        2
  •  0
  •   slider    6 年前

    如果您的视图集是 ModelViewSet perform_update 钩子(因为 模型视图集 GenericAPIView (看看“保存和删除挂钩”)。您可以使用序列化程序的 instance 字段:

    class MyViewSet(viewsets.ModelViewSet):
        # ... other stuff
    
        def perform_update(self, serializer):
            serializer.save(contact=serializer.instance.contact)
    

    所以您必须提供一个联系人,但无论您提供的是哪一个联系人,更新时都将使用旧的保存联系人。