如何使用 Django Rest Framework 修补单个字段?
How to PATCH a single field using Django Rest Framework?
我有一个包含许多字段的模型 'MyModel',我想使用 PATCH 方法更新一个字段 'status'。我正在使用基于 class 的视图。有什么办法可以实现PATCH吗?
序列化程序允许 partial updates by specifying partial=True
when initializing the serialzer. This is how PATCH
requests are handled by default in the generic views。
serializer = CommentSerializer(comment, data=request.data, partial=True)
这将允许您更新序列化程序中的单个字段,或者如果需要,可以更新所有字段,而不受标准 PUT
请求的任何限制。
它似乎开箱即用。在您的浏览器 API 上,导航到模型详细信息页面,在 HTML Form
选项卡旁边的底部单击 Raw data
,删除 JSON 字符串中除 ID 字段之外的所有内容,然后您要更改的字段,然后单击 PATCH
。执行部分 PATCH
更新。
我正在使用 djangorestframework==3.2.4
,无需对我的 ViewSet 和序列化器执行任何操作即可启用此功能。
在这个例子中,我们正在更新模型的 bool status_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 调用成功后更新复选框值。我认为这会导致人们反复点击慢速连接的复选框。
正如 stated you could use the partial=True
, which 所阐明的那样。
我只想更正它们并说您可以自由使用泛型,具体取决于您使用的 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
我为此纠结了一段时间,但它是使用通用视图或通用视图与混入的组合的非常简单的实现。
在使用通用更新视图(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 field,但是你要注意的代码是patch函数。
如果有人仍然计划使用 ModelSerializer
找到一个简单的解决方案而不改变您的大部分观点,您可以子类化 ModelSerializer
并让您的所有 ModelSerializer
继承自它.
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
我有一个包含许多字段的模型 'MyModel',我想使用 PATCH 方法更新一个字段 'status'。我正在使用基于 class 的视图。有什么办法可以实现PATCH吗?
序列化程序允许 partial updates by specifying partial=True
when initializing the serialzer. This is how PATCH
requests are handled by default in the generic views。
serializer = CommentSerializer(comment, data=request.data, partial=True)
这将允许您更新序列化程序中的单个字段,或者如果需要,可以更新所有字段,而不受标准 PUT
请求的任何限制。
它似乎开箱即用。在您的浏览器 API 上,导航到模型详细信息页面,在 HTML Form
选项卡旁边的底部单击 Raw data
,删除 JSON 字符串中除 ID 字段之外的所有内容,然后您要更改的字段,然后单击 PATCH
。执行部分 PATCH
更新。
我正在使用 djangorestframework==3.2.4
,无需对我的 ViewSet 和序列化器执行任何操作即可启用此功能。
在这个例子中,我们正在更新模型的 bool status_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 调用成功后更新复选框值。我认为这会导致人们反复点击慢速连接的复选框。
正如 partial=True
, which
我只想更正它们并说您可以自由使用泛型,具体取决于您使用的 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
我为此纠结了一段时间,但它是使用通用视图或通用视图与混入的组合的非常简单的实现。
在使用通用更新视图(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 field,但是你要注意的代码是patch函数。
如果有人仍然计划使用 ModelSerializer
找到一个简单的解决方案而不改变您的大部分观点,您可以子类化 ModelSerializer
并让您的所有 ModelSerializer
继承自它.
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