@csrf_exempt перестал работать в Django 1.4

У меня есть следующий код, который отлично работал в Django 1.2.5:

from django.views.decorators.csrf import csrf_exempt

class ApiView(object):
    def __call__(self, request, *args, **kwargs):
        method = request.method.upper()
        return getattr(self, method)(request, *args, **kwargs)

@csrf_exempt
class MyView(ApiView):

    def POST(self):
       # (...)
       return HttpResponse(json.dumps(True), mimetype="text/javascript")

Но когда я обновился до Django 1.4, я начал получать 403 запрещено с сообщением «Ошибка проверки CSRF».

Почему этот декоратор @csrf_exempt не работает?

Определение URL:

from django.conf.urls.defaults import *
from django.views.decorators.csrf import csrf_exempt

import views

urlpatterns = patterns('',
   url(r'^myview/(?P<parameter_name>[A-Za-z0-9-_]+)/$',
       views.MyView(),
       name="myproject-myapp-myview",
       ),
)

person lfagundes    schedule 20.04.2012    source источник
comment
Примечание. Вызов представления таким образом не является потокобезопасным. Вы должны создавать новый экземпляр для каждого вызова.   -  person Willian    schedule 24.04.2012
comment
Не могли бы вы дать определение URL-адреса для представления ??   -  person Sandip Agarwal    schedule 28.08.2012


Ответы (3)


Согласно документации django:

Чтобы украсить каждый экземпляр представления на основе классов, вам нужно украсить само определение класса. Для этого вы применяете декоратор к методу dispatch() класса.

Итак, вам нужно сделать что-то вроде:

class MyView(ApiView):

    def POST(self):
       # (...)
       return HttpResponse(json.dumps(True), mimetype="text/javascript")

    @csrf_exempt
    def dispatch(self, *args, **kwargs):
        return super(MyView, self).dispatch(*args, **kwargs)
person dgel    schedule 20.04.2012
comment
Поскольку постер использует POST заглавными буквами, я не думаю, что он использует представления на основе класса django. - person Willian; 21.04.2012
comment
@william- Хороший улов. Тогда этот ответ не подходит. - person dgel; 21.04.2012
comment
да, я не использую представление на основе класса django. Яm very sorry that I missed that MyView is a callable, as ApiView implements __call__ (Iм храню чужой код). Итак, этот класс является вызываемым, и @csrf_exempt в классе раньше работал в django 1.2, но не в 1.4. - person lfagundes; 23.04.2012
comment
В любом случае это не сработает, даже для представления на основе классов. Согласно документам, вы должны обернуть декоратор csrf_exempt в декоратор method_decorator: @method_decorator(csrf_exempt) - person Chad; 19.07.2013
comment
Ну наконец то. СЛАВА БОГУ. Это было чертовски сложно. Спасибо за ответ, который действительно работает. - person dan-klasson; 04.05.2017

Просто используйте csrf_exempt в urls.py. то есть::

urls.py

..other imports...
from django.views.decorators.csrf import csrf_exempt   
from myapp.views import MyView

urlpatterns = patterns('',
   url(r'^myview/(?P<parameter_name>[A-Za-z0-9-_]+)/$',
       csrf_exempt(MyView.as_view()), # use csrf_exempt here
       name="myproject-myapp-myview",
       ),
)
person suhailvs    schedule 13.04.2014

csrf_exempt должен украшать функцию. В своих URL-адресах вы можете украсить эту функцию, документы можно найти здесь.

(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
person Willian    schedule 20.04.2012
comment
Извините, я не заметил важного факта: этот класс является вызываемым. Я только что обновил вопрос. - person lfagundes; 23.04.2012