3
Solution 1: With the @override_default()
wrapper
You want to apply a wrapper function to the viewset
that you wish to override with this value:
from rest_framework.throttling import UserRateThrottle
class UserViewSet(viewsets.ViewSet):
@api_view(['PUT'])
@throttle_classes([UserRateThrottle])
@override_settings(REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']['user'] = "2/day")
def update(self, request, pk=None):
...
Add the wrapper before any view or viewset you wish to apply this overridden customs value.
You also want this in your settings.py
:
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '13500/day'
}
}
Solution 2: Custom throttling class
However, if you want different throttling rates for when you’re in a test environment, perhaps try the following in settings.py
:
TEST = True ## <-- Set to False when not in testing!!
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.CustomUserRateThrottle'
)
}
And designate your own custom throttling class:
from django.conf import settings
class CustomUserRateThrottle(throttling.UserRateThrottle):
if settings.TEST:
THROTTLE_RATES = 'DEFAULT_THROTTLE_RATES': {
'user': '13500/day',
}
else:
THROTTLE_RATES = 'DEFAULT_THROTTLE_RATES': {
'user': '2/day',
}
return settings.TEST # <-- Custom throttling classes must always return either True or False, so this makes sense.
Solution 3: directly in your “testing shell”:
Include your custom wrapper as we defined above but this time in your test_something()
method in test.py
:
from django.conf import settings
from django.test import TestCase
class TestCase(TestCase):
def test_something(self):
with self.settings(REST_FRAMEWORK = ['DEFAULT_THROTTLE_RATES']['user'] = '13500/day'):
# START TESTING HERE WITH TEST SETTINGS
5
from unittest import mock
@mock.patch('rest_framework.throttling.SimpleRateThrottle.get_rate')
def test_api(self, get_rate):
get_rate.return_value = '1/minute'
from rest_framework.settings import api_settings
print(api_settings.DEFAULT_THROTTLE_RATES)
print(api_settings.user_settings)
url = 'api'
response = self.client.get(url)
self.assertEqual(response.status_code, HTTP_200_OK)
response = self.client.get(url)
self.assertEqual(response.status_code, HTTP_429_TOO_MANY_REQUESTS)
2
Depending on your use case you can follow one of the following ways :
Suggestion 1 : If you want to override settings in few specific test cases the you can use @override_settings
decorator. But this make no sense if you want that for all test cases, if that’s the case then you can follow suggestion 2.
Suggestion 2 : This is more generic and efficient solution.
You can have several settings file for various running environment (inside settings python module) something like this:
base.py
(containing all of your basic settings)local.py
(import * from base here and override/add settings specific to local/dev environment)test.py
(import * from base here and override/add settings specific to test environment)- you can also have a settings specific for production environment in
prod.py
or something.
With this setup can run tests like python manage.py test --settings=yourproject.settings.test