我有一个包含许多字段的模型“MyModel”,我想使用 PATCH 方法更新字段“状态”。我正在使用基于类的视图。有什么方法可以实现 PATCH?
5 回答
序列化器通过指定partial=True
何时初始化序列化器来允许部分更新。这就是在通用视图中默认PATCH
处理请求的方式。
serializer = CommentSerializer(comment, data=request.data, partial=True)
这将允许您更新序列化程序中的单个字段,或者如果需要,可以更新所有字段,而不受标准PUT
请求的任何限制。
正如凯文布朗所说,你可以使用partial=True
,chefarov很好地澄清了这一点。
我只想更正它们并说您可以自由使用泛型,具体取决于您使用的 HTTP 方法:
如果您使用的是 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)
这会将序列化程序创建为部分,其余的泛型将像魅力一样工作,而无需对 update/partial_update 机制进行任何手动干预。
在引擎盖下
我使用了泛型: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)
…
因此,如果您覆盖该get_serializer
函数,您实际上可以覆盖部分参数并强制它为真。
请注意,如果您只希望部分 HTTP 方法使用它,这会使这种方法更加困难。
我正在使用djangorestframework==3.5.3
它似乎是开箱即用的。在您的浏览器 API 上,导航到模型详细信息页面,在选项卡旁边的底部HTML Form
单击Raw data
,从 JSON 字符串中删除除 ID 字段和您要更改的字段之外的所有内容,然后单击PATCH
。执行部分PATCH
更新。
我正在使用djangorestframework==3.2.4
,并且不需要对我的 ViewSets 和 Serializers 做任何事情来启用它。
在这个例子中,我们正在更新模型的 boolstatus_field
字段,我使用的是 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>
然后在一个<form>
:
<input type="checkbox" id="status_field" {% if your_rendering_context.status_field %}
checked {% endif %} >
我选择允许复选框更改,然后在失败的情况下恢复它。但是您可以替换click
为mousedown
仅在 AJAX 调用成功后才更新复选框值。我认为这会导致人们反复点击慢速连接复选框。
如果有人仍然计划在ModelSerializer
不改变您的大部分视图的情况下找到一个简单的解决方案,您可以继承 theModelSerializer
并让您的所有ModelSerializer
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
我为此苦苦挣扎了一段时间,但它是一个非常简单的实现,它使用通用视图或通用视图和 mixin 的组合。
在使用通用更新视图(generics.UpdateAPIView)的情况下,只需使用以下代码,确保请求类型为 PATCH:
class UpdateUser(generics.UpdateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
没有别的了!
如果您将更新混合 (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)
第二个例子比较复杂,展示了如何覆盖queryset和lookup字段,但是需要注意的代码是patch函数。