51

我有一个包含许多字段的模型“MyModel”,我想使用 PATCH 方法更新字段“状态”。我正在使用基于类的视图。有什么方法可以实现 PATCH?

4

5 回答 5

51

序列化器通过指定partial=True何时初始化序列化器来允许部分更新。这就是在通用视图中默认PATCH处理请求的方式

serializer = CommentSerializer(comment, data=request.data, partial=True)

这将允许您更新序列化程序中的单个字段,或者如果需要,可以更新所有字段,而不受标准PUT请求的任何限制。

于 2015-01-16T19:42:49.813 回答
17

正如凯文布朗所说,你可以使用partial=Truechefarov很好地澄清了这一点。

我只想更正它们并说您可以自由使用泛型,具体取决于您使用的 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

于 2017-02-14T09:53:49.350 回答
5

它似乎是开箱即用的。在您的浏览器 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 %} >

我选择允许复选框更改,然后在失败的情况下恢复它。但是您可以替换clickmousedown仅在 AJAX 调用成功后才更新复选框值。我认为这会导致人们反复点击慢速连接复选框。

于 2016-02-29T16:04:04.737 回答
5

如果有人仍然计划在ModelSerializer不改变您的大部分视图的情况下找到一个简单的解决方案,您可以继承 theModelSerializer并让您的所有ModelSerializers 都继承自它。

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
于 2018-10-26T10:57:52.913 回答
2

我为此苦苦挣扎了一段时间,但它是一个非常简单的实现,它使用通用视图或通用视图和 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函数。

于 2017-11-09T01:30:20.590 回答