[Fixed]-Django @csrf_exempt not working in class View

8👍

I found out the way to solve this. You need to create a middleware that calls before any Session Middlewares and then check against your desired urls or app to exempt the CSRF token validation. So, the code would be like this:

settings.py

MIDDLEWARE_CLASSES = [
    'api.middleware.DisableCSRF',  # custom middleware for API
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'a9.utils.middleware.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'a9.core.access.middleware.AccessMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
]

urls.py

app_name = "api"

urlpatterns = [
    url(r'^v1/', include([
        url(r'^', include(router.urls)),
        url(r'^auth/', MyAuthentication.as_view()),
        url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
        url(r'^admin/', include(admin.site.urls)),
    ])),
]

csrf_disable.py

from django.core.urlresolvers import resolve
# django2

    
class DisableCSRF(object):
    """Middleware for disabling CSRF in an specified app name.
    """

    def process_request(self, request):
        """Preprocess the request.
        """
        app_name = "api"
        if resolve(request.path_info).app_name == app_name:
            setattr(request, '_dont_enforce_csrf_checks', True)
        else:
            pass  # check CSRF token validation

This will only check CSRF token against a specific app or url without removing all the CSRF. Also, this is django-rest-framework independent 🙂

👤Carlos

8👍

DO NOT USE csrf_exempt with Django REST framework.

This won’t work because the SessionAuthentication enforces the csrf check anyway.

Please make sure you use the csrf token in your AJAX requests. Django has a comprehensive documentation about it

7👍

You need to decorate the csrf_exempt inside the dispatch method.

class MyView(FormView):

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(MyView, self).dispatch(*args, **kwargs)

    def post(self, request, *args, **kwargs):
        # ....
        return super(MyView, self).post(request, *args, **kwargs)

0👍

In my case in django3.2 while using DRF, and function based view. I had to explicitly set permission_classes to []

@api_view(["GET"])
@permission_classes([])
def ping(*args, **kwargs):
    """
    Used to double check that the api is up an running.
    """
    return Response({"msg": "pong"}, status=200)

I believe a class based view might be similar:

class PingView(ListAPIView):
    permission_classes = []
    pagination_class = None
    serializer_class = None
    def get(self):
        return Response({"msg": "pong"}, status=200)

Leave a comment