diff --git a/rest_framework/compat.py b/rest_framework/compat.py index b0367a32c..735f3a73d 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -59,6 +59,10 @@ else: update_wrapper(view, cls.dispatch, assigned=()) return view +http_method_names = set(View.http_method_names) +http_method_names.add('patch') +View.http_method_names = list(http_method_names) # PATCH method is not implemented by Django + # PUT, DELETE do not require CSRF until 1.4. They should. Make it better. if django.VERSION >= (1, 4): from django.middleware.csrf import CsrfViewMiddleware diff --git a/rest_framework/generics.py b/rest_framework/generics.py index 27540a57f..4c0c4d10b 100644 --- a/rest_framework/generics.py +++ b/rest_framework/generics.py @@ -138,11 +138,14 @@ class UpdateAPIView(mixins.UpdateModelMixin, SingleObjectAPIView): """ - Concrete view for updating a model instance. + Concrete view for updating or partially updating a model instance. """ def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) + def patch(self, request, *args, **kwargs): + return self.partially_update(request, *args, **kwargs) + class ListCreateAPIView(mixins.ListModelMixin, mixins.CreateModelMixin, @@ -175,7 +178,7 @@ class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin, mixins.DestroyModelMixin, SingleObjectAPIView): """ - Concrete view for retrieving, updating or deleting a model instance. + Concrete view for retrieving, updating, partially updating, or deleting a model instance. """ def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) @@ -183,5 +186,8 @@ class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin, def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) + def patch(self, request, *args, **kwargs): + return self.partially_update(request, *args, **kwargs) + def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs) diff --git a/rest_framework/mixins.py b/rest_framework/mixins.py index 8873e4aed..d220afdea 100644 --- a/rest_framework/mixins.py +++ b/rest_framework/mixins.py @@ -82,7 +82,21 @@ class UpdateModelMixin(object): self.object = None serializer = self.get_serializer(data=request.DATA, instance=self.object) + if serializer.is_valid(): + self.pre_save(serializer.object) + self.object = serializer.save() + return Response(serializer.data) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def partially_update(self, request, *args, **kwargs): + """ + Updates model instance with only the fields present in request.DATA. + """ + self.object = self.get_object() + data = self.get_serializer(instance=self.object).data + data.update(request.DATA) # overwrite data with data from the request + serializer = self.get_serializer(data=data, instance=self.object) if serializer.is_valid(): self.pre_save(serializer.object) self.object = serializer.save()