Disable LoginRequiredMiddleware on DRF views

This commit is contained in:
Bruno Alla 2024-08-30 18:42:43 +01:00
parent d295dfe5a7
commit dee68ecfce
No known key found for this signature in database
3 changed files with 22 additions and 0 deletions

View File

@ -8,6 +8,7 @@ methods on viewsets that should be included by routers.
""" """
import types import types
from django import VERSION as DJANGO_VERSION
from django.forms.utils import pretty_name from django.forms.utils import pretty_name
from rest_framework.views import APIView from rest_framework.views import APIView
@ -73,6 +74,11 @@ def api_view(http_method_names=None):
WrappedAPIView.schema = getattr(func, 'schema', WrappedAPIView.schema = getattr(func, 'schema',
APIView.schema) APIView.schema)
# Exempt all DRF views from Django's LoginRequiredMiddleware. Users should set
# DEFAULT_PERMISSION_CLASSES to 'rest_framework.permissions.IsAuthenticated' instead
if DJANGO_VERSION >= (5, 1):
func.login_required = False
return WrappedAPIView.as_view() return WrappedAPIView.as_view()
return decorator return decorator

View File

@ -1,6 +1,7 @@
""" """
Provides an APIView class that is the base of all views in REST framework. Provides an APIView class that is the base of all views in REST framework.
""" """
from django import VERSION as DJANGO_VERSION
from django.conf import settings from django.conf import settings
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db import connections, models from django.db import connections, models
@ -139,6 +140,11 @@ class APIView(View):
view.cls = cls view.cls = cls
view.initkwargs = initkwargs view.initkwargs = initkwargs
# Exempt all DRF views from Django's LoginRequiredMiddleware. Users should set
# DEFAULT_PERMISSION_CLASSES to 'rest_framework.permissions.IsAuthenticated' instead
if DJANGO_VERSION >= (5, 1):
view.login_required = False
# Note: session based authentication is explicitly CSRF validated, # Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt. # all other authentication is CSRF exempt.
return csrf_exempt(view) return csrf_exempt(view)

View File

@ -1,5 +1,7 @@
import copy import copy
import unittest
from django import VERSION as DJANGO_VERSION
from django.test import TestCase from django.test import TestCase
from rest_framework import status from rest_framework import status
@ -81,6 +83,10 @@ class ClassBasedViewIntegrationTests(TestCase):
assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.status_code == status.HTTP_400_BAD_REQUEST
assert sanitise_json_error(response.data) == expected assert sanitise_json_error(response.data) == expected
@unittest.skipUnless(DJANGO_VERSION >= (5, 1), 'Only for Django 5.1+')
def test_django_51_login_required_disabled(self):
assert self.view.login_required is False
class FunctionBasedViewIntegrationTests(TestCase): class FunctionBasedViewIntegrationTests(TestCase):
def setUp(self): def setUp(self):
@ -95,6 +101,10 @@ class FunctionBasedViewIntegrationTests(TestCase):
assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.status_code == status.HTTP_400_BAD_REQUEST
assert sanitise_json_error(response.data) == expected assert sanitise_json_error(response.data) == expected
@unittest.skipUnless(DJANGO_VERSION >= (5, 1), 'Only for Django 5.1+')
def test_django_51_login_required_disabled(self):
assert self.view.login_required is False
class TestCustomExceptionHandler(TestCase): class TestCustomExceptionHandler(TestCase):
def setUp(self): def setUp(self):