#20908 closed Bug (invalid)

csrf_exempt does not work with `__call__`

Reported by: akshar Owned by: nobody
Component: CSRF Version: 1.5
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Suppose my view is like:

class Resource(object):

@csrf_exempt
def call(self, request, *args, **kwargs):

#dispatch to any other method and get response
#return response

#urls.py

resource = Resource()

url(r'resource/$', resource, name='resource')

Now if I try to make a POST request to this url, it gives '403 Forbidden'.
Same issue on SO can be found at http://stackoverflow.com/questions/10252238/csrf-exempt-stopped-working-in-django-1-4

What I guess is happening:

On line https://github.com/django/django/blob/1.5/django/core/handlers/base.py#L104

If it were a function based view, callback would have been a csrf_exempt decorated function and CsrfViewMiddleware processing would have left it to pass without raising a 403, because this decorated function would have had an attribute csrf_exempt.

But since it is not a FBV, callback says it is still an object, something like <app.views.Resource object at 0xb5f8352c>. So, function decoration of call has not taken place till this point and so the CsrfViewMiddleware returns a 403.

Change History (1)

comment:1 Changed 22 months ago by mjtamlyn

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

You may be able to work around this by decorating the class instead of the call method. The code looks for an attribute on the "function" added by the decorator which is not present when you add it to the method.

Alternatively, if you can use the built in class based views (which I would strongly recommend to avoid state leak - this __call__ approach is potentially dangerous), then you can use the following approach:

class MyView(View):
    @classonlymethod
    def as_view(cls, **kwargs):
        return csrf_exempt(super(MyView, cls).as_view(**kwargs)

It is possible documenting this approach (assuming it works) could be helpful.

Note: See TracTickets for help on using tickets.
Back to Top