3π
I know it is too late to answer this question, but I would like to answer it for those others who might be interested.
By default, GET
and DELETE
are idempotent since the only possible response states are either 404
or sending data, but not PUT
or if we needed to make any POST request idempotent. for PUT
the most common way is the validation of input data. Make sure that all the fields of the model(including id
) are passed in unless the client receives 400 bad request
this way since even id is passed in no one can add unwanted records to the database. another way to be 100% sure everything is idempotent, is we may use cache to store the request body and userβs id as hash into cache server for enough amount of time. something like this:
# in views.py
# for DRF
import hashlib
from django.core.cache import cache
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class IdempotentView(APIView):
def put(self, req, pk, format=None):
key = hashlib.blake2b(
f"{req.user.username}, {req.body},{pk}".encode("utf-8")
).hexdigest()
is_cached = cache.get(key)
if is_cached :
return Response (req.body, status=status.HTTP_201_CREATED)
# preform the view commands then:
expiary = 60*60*3 # 3 hours
cache.set(key, 'True' , exp_date)
return Response (data, status=status.HTTP_201_CREATED)
0π
I believe the following post can shed a light on the topic: Create or Update (with PUT) in Django Rest Framework
Quote:
class ResourceViewSet(viewsets.ModelViewSet):
"""
This endpoint provides `create`, `retrieve`, `update` and `destroy` actions.
"""
queryset = Resource.objects.all()
serializer_class = ResourceSerializer
def get_object(self):
if self.request.method == 'PUT':
resource = Resource.objects.filter(id=self.kwargs.get('pk')).first()
if resource:
return resource
else:
return Resource(id=self.kwargs.get('pk'))
else:
return super(ResourceViewSet, self).get_object()
but more elegant solution which also checks for permissions β is https://gist.github.com/tomchristie/a2ace4577eff2c603b1b