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.
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)