Python 如何使用 Django Rest Framework 修补单个字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27980390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to PATCH a single field using Django Rest Framework?
提问by pnhegde
I have a model 'MyModel' with many fields and I would like to update a field 'status' using PATCH method. I'm using class based views. Is there any way to implement PATCH?
我有一个包含许多字段的模型“MyModel”,我想使用 PATCH 方法更新字段“状态”。我正在使用基于类的视图。有没有办法实现PATCH?
采纳答案by Kevin Brown
Serializers allowpartial updates by specifying partial=Truewhen initializing the serialzer. This is how PATCHrequests are handledby default in the generic views.
序列化器通过partial=True在初始化序列化器时指定来允许部分更新。这是默认情况下在通用视图PATCH中处理请求的方式。
serializer = CommentSerializer(comment, data=request.data, partial=True)
This will allow you to update individual fields in a serializer, or all of the fields if you want, without any of the restrictions of a standard PUTrequest.
这将允许您更新序列化程序中的单个字段或所有字段(如果需要),而不受标准PUT请求的任何限制。
回答by Chris
It does seem to be supported out of the box. On your browser API, navigate to a model detail page, at the bottom next to the HTML Formtab click Raw data, delete everything from the JSON string except the ID field and the field you wish to change, and click PATCH. A partial PATCHupdate is performed.
它似乎是开箱即用的。在您的浏览器 API 上,导航到模型详细信息页面,在HTML Form选项卡旁边的底部单击Raw data,从 JSON 字符串中删除除 ID 字段和您希望更改的字段之外的所有内容,然后单击PATCH。PATCH执行部分更新。
I'm using djangorestframework==3.2.4, and haven't had to do anything to my ViewSets and Serializers to enable this.
我正在使用djangorestframework==3.2.4,并且无需对我的 ViewSet 和序列化程序执行任何操作即可启用此功能。
In this exampe we are updating the bool status_fieldfield of the model, and I'm using jquery 2.2.1. Add the following to the <head>:
在这个例子中,我们正在更新status_field模型的 bool字段,我使用的是 jquery 2.2.1。将以下内容添加到<head>:
<script src="{% static 'my_app/jquery.min.js' %}"></script>
<script>
$(document).ready(function(){
var chk_status_field = $('#status_field');
chk_status_field.click(function(){
$.ajax({url: "{% url 'model-detail' your_rendering_context.id %}",
type: 'PATCH', timeout: 3000, data: { status_field: this.checked }
})
.fail(function(){
alert('Error updating this model instance.');
chk_status_field.prop('checked', !chk_status_field.prop('checked'));
});
});
});
</script>
Then in a <form>:
然后在一个<form>:
<input type="checkbox" id="status_field" {% if your_rendering_context.status_field %}
checked {% endif %} >
I chose to permit the checkbox to change, then revert it in the case of failure. But you could replace clickwith mousedownto only update the checkbox value once the AJAX call has succeeded. I think this will lead to people repeatedly clicking the checkbox for slow connections though.
我选择允许复选框更改,然后在失败的情况下将其还原。但是你可以替换click使用mousedown,一旦AJAX调用成功只更新复选框值。我认为这会导致人们反复点击连接缓慢的复选框。
回答by Uri Shalit
As Kevin Brownstated you could use the partial=True, which chefarovclarified nicely.
正如凯文·布朗所说,你可以使用partial=True,chevearov很好地澄清了这一点。
I would just like to correct them and say you could use generics freely, depending on the HTTP method you are using:
我只想更正它们并说您可以自由使用泛型,具体取决于您使用的 HTTP 方法:
If you are using PATCH HTTP method like asked, you get it out of the box. You can see
UpdateModelMixincode forpartial_update:def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return self.update(request, *args, **kwargs)For any HTTP method different from PATCH, this can be accomplished by just overriding the
get_serializermethod as follows:def get_serializer(self, *args, **kwargs): kwargs['partial'] = True return super(YOUR_CLASS, self).get_serializer(*args, **kwargs)
如果您正在使用 PATCH HTTP 方法,那么您就可以立即使用它。您可以看到以下
UpdateModelMixin代码partial_update:def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return self.update(request, *args, **kwargs)对于不同于 PATCH 的任何 HTTP 方法,这可以通过
get_serializer如下覆盖该方法来实现:def get_serializer(self, *args, **kwargs): kwargs['partial'] = True return super(YOUR_CLASS, self).get_serializer(*args, **kwargs)
This will create the serializer as partial, and the rest of the generics will work like a charm without any manual intervention in the update/partial_update mechanism.
这将创建部分序列化程序,其余的泛型将像魅力一样工作,无需对 update/partial_update 机制进行任何手动干预。
Under the hood
引擎盖下
I used the generic: generics.UpdateAPIViewwhich uses the UpdateModelMixinwhich has this code:
我使用了 generic:generics.UpdateAPIView它使用UpdateModelMixin具有以下代码的 :
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
…
So, if you override the get_serializerfunction, you can actually override the partial argument and force it to be true.
因此,如果您覆盖该get_serializer函数,您实际上可以覆盖部分参数并强制它为真。
Please note, that if you want it partial only for some of the HTTP methods, this makes this approach more difficult.
请注意,如果您只想对某些 HTTP 方法进行部分处理,这会使这种方法更加困难。
I am using djangorestframework==3.5.3
我正在使用djangorestframework==3.5.3
回答by user2583728
I struggled with this one for a while, but it is a very straightforward implementation using generic views or a combination of generic views and mixins.
我在这个问题上挣扎了一段时间,但它是一个非常简单的实现,使用通用视图或通用视图和 mixin 的组合。
In the case of using a generic update view (generics.UpdateAPIView), just use the following code, making sure the request type is PATCH:
在使用通用更新视图(generics.UpdateAPIView)的情况下,只需使用以下代码,确保请求类型为 PATCH:
class UpdateUser(generics.UpdateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
There's nothing else to it!
没有别的了!
If you're using an update mixin (mixins.UpdateModelMixin) in combination with a generic view (generics.GenericAPIView), use the following code, making sure the request type is PATCH:
如果您将更新混合 (mixins.UpdateModelMixin) 与通用视图 (generics.GenericAPIView) 结合使用,请使用以下代码,确保请求类型为 PATCH:
class ActivateUser(mixins.UpdateModelMixin, generics.GenericAPIView):
serializer_class = UserSerializer
model = User
lookup_field = 'email'
def get_queryset(self):
queryset = self.model.objects.filter(active=False)
return queryset
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
The second example is more complex, showing you how to override the queryset and lookup field, but the code you should pay attention to is the patch function.
第二个例子比较复杂,向你展示了如何覆盖queryset和lookup字段,但你应该注意的代码是patch函数。
回答by firecast
If anyone is still planning to find a simple solution using ModelSerializerwithout changing much of your views, you can subclass the ModelSerializerand have all your ModelSerializers inherit from that.
如果有人仍然打算在ModelSerializer不更改您的大部分视图的情况下找到一个简单的解决方案,您可以ModelSerializer将ModelSerializers子类化并让您的所有s 都从中继承。
class PatchModelSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
kwargs['partial'] = True
super(PatchModelSerializer, self).__init__(*args, **kwargs)
class ArticleSerializer(PatchModelSerializer):
class Meta:
model = Article

