Django Rest Framework部分更新

int*_*lis 45 python django django-rest-framework

我正在尝试partial_update使用Django Rest Framework实现,但我需要一些澄清,因为我被卡住了.

  1. 为什么我们需要指定partial = True?
    根据我的理解,我们可以轻松更新partial_update方法内的Demo对象.这样做的目的是什么?

  2. 什么是序列化变量?方法
    serialized变量的内部是什么partial_update?那是一个Demo对象吗?在幕后调用什么功能?

  3. 如何在这里完成实施?

视图集

class DemoViewSet(viewsets.ModelViewSet):
    serializer_class = DemoSerializer

    def partial_update(self, request, pk=None):
        serialized = DemoSerializer(request.user, data=request.data, partial=True)
        return Response(status=status.HTTP_202_ACCEPTED)
Run Code Online (Sandbox Code Playgroud)

串行

class DemoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Demo
        fields = '__all__'

    def update(self, instance, validated_data):
        print 'this - here'
        demo = Demo.objects.get(pk=instance.id)
        Demo.objects.filter(pk=instance.id)\
                           .update(**validated_data)
        return demo
Run Code Online (Sandbox Code Playgroud)

Eni*_*nix 72

我有与你之前相同的问题,但是当我深入研究rest_framework的源代码时,我得到了以下结论,希望它会有所帮助:

对于问题1)

这个问题与HTTP动词有关.

PUT:PUT方法用请求有效载荷替换目标资源的所有当前表示.

PATCH:PATCH方法用于对资源应用部分修改.

一般来说,partial用于检查客户端向视图提交数据时是否需要模型中的字段进行字段验证.

例如,我们有一个Book这样的模型,请注意两个nameauthor_name字段都是必需的(不是空的而不是空白).

class Book(models.Model):
    name = models.CharField('name of the book', max_length=100)
    author_name = models.CharField('the name of the author', max_length=50)

# Create a new instance for testing
Book.objects.create(name='Python in a nut shell', author_name='Alex Martelli')
Run Code Online (Sandbox Code Playgroud)

对于某些场景,我们可能只需要更新模型中的部分字段,例如,我们只需要更新name字段中的字段Book.因此,对于这种情况,客户端将仅向name视图提交具有新值的字段.从客户端提交的数据可能如下所示:

{"pk": 1, name: "PYTHON IN A NUT SHELL"}
Run Code Online (Sandbox Code Playgroud)

但您可能已经注意到我们的模型定义不允许author_name为空白.所以我们必须使用partial_update而不是update.因此,其余框架不会对请求数据中缺少的字段执行字段验证检查.

出于测试目的,您可以创建两个两个视图updatepartial_update,你会得到更多的理解,我刚才说的.

例:

views.py
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import UpdateModelMixin
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book


class BookUpdateView(GenericAPIView, UpdateModelMixin):
    '''
    Book update API, need to submit both `name` and `author_name` fields
    At the same time, or django will prevent to do update for field missing
    '''
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

class BookPartialUpdateView(GenericAPIView, UpdateModelMixin):
    '''
    You just need to provide the field which is to be modified.
    '''
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def put(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud) urls.py
urlpatterns = patterns('',
    url(r'^book/update/(?P<pk>\d+)/$', BookUpdateView.as_view(), name='book_update'),
    url(r'^book/update-partial/(?P<pk>\d+)/$', BookPartialUpdateView.as_view(), name='book_partial_update'),
)
Run Code Online (Sandbox Code Playgroud)

要提交的数据

{"pk": 1, name: "PYTHON IN A NUT SHELL"}
Run Code Online (Sandbox Code Playgroud)

当您将上述json提交给/book/update/1/,您将在HTTP_STATUS_CODE = 400时出现以下错误:

{
  "author_name": [
    "This field is required."
  ]
}
Run Code Online (Sandbox Code Playgroud)

但是当你提交上面的json时/book/update-partial/1/,你会得到HTTP_STATUS_CODE = 200以及以下响应,

{
  "id": 1,
  "name": "PYTHON IN A NUT SHELL",
  "author_name": "Alex Martelli"
}
Run Code Online (Sandbox Code Playgroud)

对于问题2)

serialized是一个将模型实例包装为可序列化对象的对象.并且您可以使用此序列化生成一个普通的JSON字符串serialized.data.

对于问题3)

我认为你在阅读上面的答案后可以自己回答,你应该知道何时使用update以及何时使用partial_update.

如果您还有任何疑问,请随时提出.我只是阅读了部分源代码的休息框架,对于某些术语可能还不太了解,请在出错时指出...


Goo*_*han 30

用于部分更新 - PATCH http方法

对于完全更新 - PUT HTTP方法

使用DRF进行更新时,您应该发送包含所有(必需)字段值的请求数据.当请求是通过PUT http方法时,至少就是这种情况.据我所知,您想要更新一个或至少不是所有模型实例字段.在这种情况下,使用PATCH http方法发出请求.Django休息框架(DRF)将开箱即用.

示例(使用令牌身份验证):

curl -i -X PATCH -d '{"name":"my favorite banana"}' -H "Content-Type: application/json" -H 'Authorization: Token <some token>'  http://localhost:8000/bananas/
Run Code Online (Sandbox Code Playgroud)


Ali*_*tov 7

如此简单,只需像这样覆盖序列化程序的init方法:

def __init__(self, *args, **kwargs):
    kwargs['partial'] = True
    super(DemoSerializer, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

  • 我想知道为什么这个答案没有得到更多的赞成票?这对我来说就像一种魅力 (2认同)
  • 在更新函数中,partial=False 被替换。只需使用 PATCH 而不是 PUT。 (2认同)

Ser*_*ini 5

只是一个简短的说明,因为似乎没有人已经指出了这一点:

serialized = DemoSerializer(request.user, data=request.data, partial=True)
Run Code Online (Sandbox Code Playgroud)

DemoSerializer 的第一个参数应该是一个 Demo 实例,而不是一个用户(至少如果你像我一样使用 DRF 3.6.2)。

我不知道你想做什么,但这是一个有效的例子:

def partial_update(self, request, *args, **kwargs):
    response_with_updated_instance = super(DemoViewSet, self).partial_update(request, *args, **kwargs)
    Demo.objects.my_func(request.user, self.get_object())
    return response_with_updated_instance
Run Code Online (Sandbox Code Playgroud)

我做部分更新,然后我做其他事情,调用 my_func 并传递当前用户和已经更新的演示实例。

希望这可以帮助。