Home > Net >  Object update by PATCH for Django REST Framework
Object update by PATCH for Django REST Framework

Time:02-05

I am using viewsets.ModelViewSet

from rest_framework import viewsets

class ProjectViewSet(viewsets.ModelViewSet):
    serializer_class = s.ProjectSerializer   
    queryset = m.Project.objects.all()

    def patch(self,request,*args,**kwargs):
      instance = self.get_object()
      serializer = self.get_serializer(instance,data = request.data)
      if serializer.is_valid():
          self.perform_update(serializer)
          return Response(serializer.data)
      return Response()

Then I test to update the object via django restframework UI.

enter image description here

enter image description here

Then this error occurs.

My basic idea that changing object data via PATCH is correct?

How can I update the data via Django REST Framework

Expected view ProjectViewSet to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.

CodePudding user response:

First, the problem is directly related to URL setup, in any case I would suggest using DRF routers:

from django.urls import path, include
from .views import ProjectViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'projects', ProjectViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
]

Secondly, the actions provided by ModelViewSet are .list(), .retrieve(), .create(), .update(), .partial_update(), and .destroy().

The action related to PATCH is partial_update, so:

class ProjectViewSet(ModelViewSet):
    serializer_class = ProjectSerializer   
    queryset = Project.objects.all()

    def partial_update(self, request, *args, **kwargs):
        partial = True
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        return Response(serializer.data)

Original code of UpdateModelMixin

.partial_update:

def partial_update(self, request, *args, **kwargs):
    kwargs['partial'] = True
    return self.update(request, *args, **kwargs)

As you can see it still calls .update which does almost exactly the same:

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)
    serializer.is_valid(raise_exception=True)
    self.perform_update(serializer)

    if getattr(instance, '_prefetched_objects_cache', None):
        # If 'prefetch_related' has been applied to a queryset, we need to
        # forcibly invalidate the prefetch cache on the instance.
        instance._prefetched_objects_cache = {}

    return Response(serializer.data)
  • Related