mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-29 17:39:48 +03:00
Basic implementation of etags
Settings and options aren't sorted at all, but the functionality exists in the rest verb methods.
This commit is contained in:
parent
2088023293
commit
ebb47bb38f
|
@ -100,8 +100,12 @@ class RetrieveModelMixin(object):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
filtered_queryset = self.filter_queryset(queryset)
|
filtered_queryset = self.filter_queryset(queryset)
|
||||||
self.object = self.get_object(filtered_queryset)
|
self.object = self.get_object(filtered_queryset)
|
||||||
|
if self.use_etags:
|
||||||
|
if self.get_etag(self.object) == request.META.get('HTTP_IF_NONE_MATCH'):
|
||||||
|
return Response(status=304)
|
||||||
|
headers = {'ETag': self.get_etag(self.object)}
|
||||||
serializer = self.get_serializer(self.object)
|
serializer = self.get_serializer(self.object)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data, headers=headers)
|
||||||
|
|
||||||
|
|
||||||
class UpdateModelMixin(object):
|
class UpdateModelMixin(object):
|
||||||
|
@ -110,6 +114,10 @@ class UpdateModelMixin(object):
|
||||||
Should be mixed in with `SingleObjectAPIView`.
|
Should be mixed in with `SingleObjectAPIView`.
|
||||||
"""
|
"""
|
||||||
def update(self, request, *args, **kwargs):
|
def update(self, request, *args, **kwargs):
|
||||||
|
header_etag = request.META.get('HTTP_IF_MATCH')
|
||||||
|
if header_etag is None:
|
||||||
|
return Response({'error': 'IF_MATCH header is required'}, status=400)
|
||||||
|
|
||||||
partial = kwargs.pop('partial', False)
|
partial = kwargs.pop('partial', False)
|
||||||
self.object = None
|
self.object = None
|
||||||
try:
|
try:
|
||||||
|
@ -121,6 +129,8 @@ class UpdateModelMixin(object):
|
||||||
created = True
|
created = True
|
||||||
success_status_code = status.HTTP_201_CREATED
|
success_status_code = status.HTTP_201_CREATED
|
||||||
else:
|
else:
|
||||||
|
if self.object.etag != header_etag:
|
||||||
|
return Response({'error': 'object has been updated since you last saw it'}, status=412)
|
||||||
created = False
|
created = False
|
||||||
success_status_code = status.HTTP_200_OK
|
success_status_code = status.HTTP_200_OK
|
||||||
|
|
||||||
|
@ -164,5 +174,7 @@ class DestroyModelMixin(object):
|
||||||
"""
|
"""
|
||||||
def destroy(self, request, *args, **kwargs):
|
def destroy(self, request, *args, **kwargs):
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
|
if self.get_etag(obj) != self.header_etag:
|
||||||
|
return Response({'error': 'object has been updated since you last saw it'}, status=412)
|
||||||
obj.delete()
|
obj.delete()
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
|
@ -398,6 +398,13 @@ class APIView(View):
|
||||||
else:
|
else:
|
||||||
handler = self.http_method_not_allowed
|
handler = self.http_method_not_allowed
|
||||||
|
|
||||||
|
if self.use_etags and request.method.lower() in ('put', 'delete'):
|
||||||
|
etag_header = request.META.get('HTTP_IF_MATCH')
|
||||||
|
if etag_header is None:
|
||||||
|
return Response({'error': 'IF_MATCH header is required'}, status=400)
|
||||||
|
else:
|
||||||
|
self.etag_header = etag_header
|
||||||
|
|
||||||
response = handler(request, *args, **kwargs)
|
response = handler(request, *args, **kwargs)
|
||||||
|
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
@ -413,3 +420,5 @@ class APIView(View):
|
||||||
a less useful default implementation.
|
a less useful default implementation.
|
||||||
"""
|
"""
|
||||||
return Response(self.metadata(request), status=status.HTTP_200_OK)
|
return Response(self.metadata(request), status=status.HTTP_200_OK)
|
||||||
|
def get_etag(self, obj):
|
||||||
|
return getattr(obj, self.etag_var)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user