I'm using Python 3.9, Django 3.2, DRF 3.12.4. I'm adding JWT authentication method using simple JWT. To test my auth method, I need to set
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
I would like to avoid editing my settings file and keep all changes in my test file. That's because I have separate local and production settings, and local settings are using fake auth backend. All tests are passing when I set the above auth class in my local settings.
I tried to use @override_settings:
@override_settings(
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
}
)
It seems to work fine - when I print the settings in my test:
from django.conf import settings
from rest_framework.settings import api_settings
...
def setUp(self):
print(settings.REST_FRAMEWORK)
print(api_settings.DEFAULT_AUTHENTICATION_CLASSES)
I get
{'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication',)}
[<class 'rest_framework_simplejwt.authentication.JWTAuthentication'>]
However, tests aren't passing - I'm getting error from my fake auth backend, as if the settings aren't getting overriden after all. I also tried editing django.conf settings directly - which is something I would rather not do, but it didn't solve my problem as well. Am I doing something wrong? Maybe my solution/tests have some logical mistakes and I'm doing something I shouldn't do? Thank you in advance for all the help.
This happens because several DRF base classes store the initial values on the class.
You can update the various cached values like this:
from rest_framework.generics import GenericAPIView
from rest_framework.settings import api_settings
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
GenericAPIView.filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
GenericAPIView.pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
APIView.renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
APIView.parser_classes = api_settings.DEFAULT_PARSER_CLASSES
APIView.authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
APIView.throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
APIView.permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
APIView.content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
APIView.metadata_class = api_settings.DEFAULT_METADATA_CLASS
APIView.versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
APIRequestFactory.renderer_classes_list = api_settings.TEST_REQUEST_RENDERER_CLASSES
APIRequestFactory.default_format = api_settings.TEST_REQUEST_DEFAULT_FORMAT
If you want to be able to have this happen automatically when using override_settings
, add a signal listener for setting_changed
.
from django.test.signals import setting_changed
from rest_framework.generics import GenericAPIView
from rest_framework.settings import api_settings
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
def reload_drf_settings(*args, **kwargs):
setting = kwargs['setting']
if setting == 'REST_FRAMEWORK':
api_settings.reload()
GenericAPIView.filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
GenericAPIView.pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
APIView.renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
APIView.parser_classes = api_settings.DEFAULT_PARSER_CLASSES
APIView.authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
APIView.throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
APIView.permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
APIView.content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
APIView.metadata_class = api_settings.DEFAULT_METADATA_CLASS
APIView.versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
APIRequestFactory.renderer_classes_list = api_settings.TEST_REQUEST_RENDERER_CLASSES
APIRequestFactory.default_format = api_settings.TEST_REQUEST_DEFAULT_FORMAT
setting_changed.connect(reload_drf_settings)