Обновление объектов с помощью PATCH для Django REST Framework
Я использую 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()
Затем я тестирую обновление объекта через django restframework UI.
Тогда возникает эта ошибка.
Моя основная идея о том, что изменение данных объекта через PATCH правильно?
Как я могу обновить данные через 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.
Во-первых, проблема напрямую связана с настройкой URL, в любом случае я бы предложил использовать DRF маршрутизаторы :
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)),
]
Во-вторых, действия, предоставляемые ModelViewSet - это .list()
, .retrieve()
, .create()
, .update()
, .partial_update()
и .destroy()
.
Действие, связанное с PATCH
, это partial_update
, поэтому:
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)
Оригинальный код UpdateModelMixin
.partial_update
:
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
Как вы можете видеть, он по-прежнему вызывает .update
, который делает почти то же самое:
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)