Hadi Farhadi
Hadi Farhadi

Reputation: 1761

django rest framework throttling per user and per view

i have two api view (django rest framework):

class ApiView1(APIView):
    ...
    throttle_classes = (UserRateThrottle, )

and api 2:

class ApiView2(APIView):
    ...
    throttle_classes = (UserRateThrottle, )

and my settings:

REST_FRAMEWORK = {
    ...,
    'DEFAULT_THROTTLE_RATES': {
        'user': '5/minute'
    }
}

when request the ApiView1 for five time, every thing is okay, but after that when request the ApiView2, i get a http 429 status code with:

Request was throttled. Expected available in 45 seconds.

Question: can i use throttling per user and per view? if yes, How it can be done?

Upvotes: 3

Views: 4254

Answers (2)

thyago stall
thyago stall

Reputation: 1704

Yes, you can.

For class-based views:

class YourView(APIView):
    throttle_classes = (UserRateThrottle, )

    def get(self, request, format=None):
        content = { ... Your response here ... }
        return Response(content)

For function-based views you can use the decorator: @throttle_classes([UserRateThrottle])

_Reference: https://www.django-rest-framework.org/api-guide/throttling/

Upvotes: 1

ramwin
ramwin

Reputation: 6276

Because it's the feature of django-rest-framework.

The ScopedRateThrottle class can be used to restrict access to specific parts of the API. This throttle will only be applied if the view that is being accessed includes a .throttle_scope property. The unique throttle key will then be formed by concatenating the "scope" of the request with the unique user id or IP address.

The allowed request rate is determined by the DEFAULT_THROTTLE_RATES setting using a key from the request "scope".

Since you don't set the throttle_scope the any view, both ApiView1 and ApiView2 use the same throttle scope scope. So they share the same limit. If one view is over-accessed, another view will be unacceptable either.

In your scenario, you should set different throttle_scope in the apiview and add the scope to REST_FRAMEWORK.DEFAULT_THROTTLE_RATES.

If you have many throttle scope and don't want to add too many scopes in settings.py, you should create your own Throttle class and override the get_cache_key function.

class MyThrottle(UserRateThrottle):
    def get_cache_key(self, request, view):
        return "throttle_{viewid}_{indent}".format(
            viewid=id(view),
            indent=self.get_indent(request)
        )

This ThrottleClass can automatic set different scope for different view.

Upvotes: 3

Related Questions