Django Rest Framework Scope Throttling On Function Based View
Solution 1:
You can solve this by creating all the custom throttling classes first. Note: Only the throttles are in classes but the views are functions.
classPostAnononymousRateThrottle(throttling.AnonRateThrottle):
scope = 'post_anon'defallow_request(self, request, view):
if request.method == "GET":
returnTruereturnsuper().allow_request(request, view)
classGetAnononymousRateThrottle(throttling.AnonRateThrottle):
scope = 'get_anon'defallow_request(self, request, view):
if request.method == "POST":
returnTruereturnsuper().allow_request(request, view)
classPostUserRateThrottle(throttling.UserRateThrottle):
scope = 'post_user'defallow_request(self, request, view):
if request.method == "GET":
returnTruereturnsuper().allow_request(request, view)
classGetUserRateThrottle(throttling.UserRateThrottle):
scope = 'get_user'defallow_request(self, request, view):
if request.method == "POST":
returnTruereturnsuper().allow_request(request, view)
You can choose to eliminate the classes if you are not looking for authentication or method type.
Then you need to import this
from rest_framework.decoratorsimport api_view, throttle_classes
Then you can wrap your function view with throttle_classes decorator with all the permissions created
@api_view(['GET', 'POST'])
@throttle_classes([PostAnononymousRateThrottle, GetAnononymousRateThrottle, PostUserRateThrottle, GetUserRateThrottle])
def someFunction(request):
if request.method == 'POST':
return Response({"message": "Got some data!", "data": request.data})
elif request.method == 'GET':
return Response({"message": "Hello, world!"})
Don't forget to mention the throttle rate in the settings.py
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'post_anon': '3/minute',
'get_anon': '1/minute',
'post_user': '2/minute',
'get_user': '2/minute'
}
}
Solution 2:
I finally found out a workaround for function based views. Here is how I implemented it.
As it was explained in previous answers, we need to extend the UserRateThrottle class or AnonRateThrottle class depending on our need.
For my case, I was more interested in throttling requests from users.
from rest_framework.throttling import UserRateThrottle
classCustomThrottle(UserRateThrottle):
scope = 'my_custom_scope'defallow_request(self, request, view):
if request.method == 'GET':
self.scope = 'get_scope'
self.rate = '2/hour'returnTruereturnsuper().allow_request(request, view)
And in the settings:
'DEFAULT_THROTTLE_RATES': {
'my_custom_scope': '3/day'
}
By default, this class will throttle POST requests based on the rate set in the settings file. The thing I added here is altering the scope and rate in case the request method was GET. Without this alteration, some problems may occur because of the default caching used by DRF Throttlers. We need to set the rate and scope inside the CustomThrottle class itself or else the scope affiliated with POST method will be applied on both GET and POST.
Finally, we add the decorator on our function-based view.
from rest_framework import api_view, throttle_classes
import CustomThrottle
@api_view(['GET', 'POST'])@throttle_classes([CustomThrottle])defsomeFunction(request):
if request.method == 'GET':
# set scope for get requestselif request.method == 'POST':
# set scope for post requests
and that'd be it :D
Post a Comment for "Django Rest Framework Scope Throttling On Function Based View"