mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-09 08:00:52 +03:00
Adding PATCH support to Django REST Framework
This commit is contained in:
parent
4f96951be9
commit
18338a37d3
|
@ -47,14 +47,14 @@ class GenericAPIView(views.APIView):
|
||||||
|
|
||||||
return serializer_class
|
return serializer_class
|
||||||
|
|
||||||
def get_serializer(self, instance=None, data=None, files=None):
|
def get_serializer(self, instance=None, data=None, files=None, partial=False):
|
||||||
"""
|
"""
|
||||||
Return the serializer instance that should be used for validating and
|
Return the serializer instance that should be used for validating and
|
||||||
deserializing input, and for serializing output.
|
deserializing input, and for serializing output.
|
||||||
"""
|
"""
|
||||||
serializer_class = self.get_serializer_class()
|
serializer_class = self.get_serializer_class()
|
||||||
context = self.get_serializer_context()
|
context = self.get_serializer_context()
|
||||||
return serializer_class(instance, data=data, files=files, context=context)
|
return serializer_class(instance, data=data, files=files, partial=partial, context=context)
|
||||||
|
|
||||||
|
|
||||||
class MultipleObjectAPIView(MultipleObjectMixin, GenericAPIView):
|
class MultipleObjectAPIView(MultipleObjectMixin, GenericAPIView):
|
||||||
|
@ -169,7 +169,17 @@ class UpdateAPIView(mixins.UpdateModelMixin,
|
||||||
Concrete view for updating a model instance.
|
Concrete view for updating a model instance.
|
||||||
"""
|
"""
|
||||||
def put(self, request, *args, **kwargs):
|
def put(self, request, *args, **kwargs):
|
||||||
return self.update(request, *args, **kwargs)
|
return self.update(request, partial=False, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ParitalUpdateAPIView(mixins.UpdateModelMixin,
|
||||||
|
SingleObjectAPIView):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Concrete view for paritally updating a model instance.
|
||||||
|
"""
|
||||||
|
def patch(self, request, *args, **kwargs):
|
||||||
|
return self.update(request, partial=True, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ListCreateAPIView(mixins.ListModelMixin,
|
class ListCreateAPIView(mixins.ListModelMixin,
|
||||||
|
@ -209,7 +219,29 @@ class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
|
||||||
return self.retrieve(request, *args, **kwargs)
|
return self.retrieve(request, *args, **kwargs)
|
||||||
|
|
||||||
def put(self, request, *args, **kwargs):
|
def put(self, request, *args, **kwargs):
|
||||||
return self.update(request, *args, **kwargs)
|
return self.update(request, partial=False, *args, **kwargs)
|
||||||
|
|
||||||
|
def delete(self, request, *args, **kwargs):
|
||||||
|
return self.destroy(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class RetrievePartialUpdateDestroyAPIView(mixins.RetrieveModelMixin,
|
||||||
|
mixins.UpdateModelMixin,
|
||||||
|
mixins.DestroyModelMixin,
|
||||||
|
SingleObjectAPIView):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Concrete view for retrieving, updating via PATCH (partial) or PUT (full),
|
||||||
|
or deleting a model instance.
|
||||||
|
"""
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
return self.retrieve(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def put(self, request, *args, **kwargs):
|
||||||
|
return self.update(request, partial=False, *args, **kwargs)
|
||||||
|
|
||||||
|
def patch(self, request, *args, **kwargs):
|
||||||
|
return self.update(request, partial=True, *args, **kwargs)
|
||||||
|
|
||||||
def delete(self, request, *args, **kwargs):
|
def delete(self, request, *args, **kwargs):
|
||||||
return self.destroy(request, *args, **kwargs)
|
return self.destroy(request, *args, **kwargs)
|
||||||
|
|
|
@ -81,7 +81,7 @@ class UpdateModelMixin(object):
|
||||||
Update a model instance.
|
Update a model instance.
|
||||||
Should be mixed in with `SingleObjectBaseView`.
|
Should be mixed in with `SingleObjectBaseView`.
|
||||||
"""
|
"""
|
||||||
def update(self, request, *args, **kwargs):
|
def update(self, request, partial=False, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
created = False
|
created = False
|
||||||
|
@ -89,7 +89,7 @@ class UpdateModelMixin(object):
|
||||||
self.object = None
|
self.object = None
|
||||||
created = True
|
created = True
|
||||||
|
|
||||||
serializer = self.get_serializer(self.object, data=request.DATA, files=request.FILES)
|
serializer = self.get_serializer(self.object, data=request.DATA, files=request.FILES, partial=partial)
|
||||||
|
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
self.pre_save(serializer.object)
|
self.pre_save(serializer.object)
|
||||||
|
|
|
@ -63,6 +63,20 @@ class DecoratorTestCase(TestCase):
|
||||||
response = view(request)
|
response = view(request)
|
||||||
self.assertEqual(response.status_code, 405)
|
self.assertEqual(response.status_code, 405)
|
||||||
|
|
||||||
|
# def test_calling_patch_method(self):
|
||||||
|
|
||||||
|
# @api_view(['GET', 'PATCH'])
|
||||||
|
# def view(request):
|
||||||
|
# return Response({})
|
||||||
|
|
||||||
|
# request = self.factory.patch('/')
|
||||||
|
# response = view(request)
|
||||||
|
# self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# request = self.factory.post('/')
|
||||||
|
# response = view(request)
|
||||||
|
# self.assertEqual(response.status_code, 405)
|
||||||
|
|
||||||
def test_renderer_classes(self):
|
def test_renderer_classes(self):
|
||||||
|
|
||||||
@api_view(['GET'])
|
@api_view(['GET'])
|
||||||
|
|
|
@ -180,6 +180,19 @@ class TestInstanceView(TestCase):
|
||||||
updated = self.objects.get(id=1)
|
updated = self.objects.get(id=1)
|
||||||
self.assertEquals(updated.text, 'foobar')
|
self.assertEquals(updated.text, 'foobar')
|
||||||
|
|
||||||
|
# def test_patch_instance_view(self):
|
||||||
|
# """
|
||||||
|
# PATCH requests to RetrieveUpdateDestroyAPIView should update an object.
|
||||||
|
# """
|
||||||
|
# content = {'text': 'foobar'}
|
||||||
|
# request = factory.patch('/1', json.dumps(content),
|
||||||
|
# content_type='application/json')
|
||||||
|
# response = self.view(request, pk=1).render()
|
||||||
|
# self.assertEquals(response.status_code, status.HTTP_200_OK)
|
||||||
|
# self.assertEquals(response.data, {'id': 1, 'text': 'foobar'})
|
||||||
|
# updated = self.objects.get(id=1)
|
||||||
|
# self.assertEquals(updated.text, 'foobar')
|
||||||
|
|
||||||
def test_delete_instance_view(self):
|
def test_delete_instance_view(self):
|
||||||
"""
|
"""
|
||||||
DELETE requests to RetrieveUpdateDestroyAPIView should delete an object.
|
DELETE requests to RetrieveUpdateDestroyAPIView should delete an object.
|
||||||
|
|
|
@ -18,7 +18,7 @@ class BasicView(APIView):
|
||||||
return Response({'method': 'POST', 'data': request.DATA})
|
return Response({'method': 'POST', 'data': request.DATA})
|
||||||
|
|
||||||
|
|
||||||
@api_view(['GET', 'POST', 'PUT'])
|
@api_view(['GET', 'POST', 'PUT', 'PATCH'])
|
||||||
def basic_view(request):
|
def basic_view(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return {'method': 'GET'}
|
return {'method': 'GET'}
|
||||||
|
@ -26,6 +26,8 @@ def basic_view(request):
|
||||||
return {'method': 'POST', 'data': request.DATA}
|
return {'method': 'POST', 'data': request.DATA}
|
||||||
elif request.method == 'PUT':
|
elif request.method == 'PUT':
|
||||||
return {'method': 'PUT', 'data': request.DATA}
|
return {'method': 'PUT', 'data': request.DATA}
|
||||||
|
elif request.method == 'PATCH':
|
||||||
|
return {'method': 'PATCH', 'data': request.DATA}
|
||||||
|
|
||||||
|
|
||||||
def sanitise_json_error(error_dict):
|
def sanitise_json_error(error_dict):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user