Skip to content Skip to sidebar Skip to footer

Django Rest Framework Scope Throttling On Function Based View

Wanted to ask if someone knows a way or a workaround to how to set different throttle scopes for different request methods in a function-based view. For example @api_view(['GET', '

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'
    }
}

Reference: https://medium.com/analytics-vidhya/throttling-requests-with-django-rest-framework-for-different-http-methods-3ab0461044c

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"