为什么在 AJAX 请求中使用 @csrf_exempt 时会出现 403 Forbidden 错误?

Why am I be getting a 403 Forbidden error when using @csrf_exempt in AJAX request?

我正在尝试在 Django 中编写一个非常基本的 AJAX 请求,但我在 Chrome Dev 和 Django 控制台中不断收到 403 forbidden 错误。前几天我发布了一个类似的问题,并尝试了所有建议的解决方案,包括 @csrf_exempt (以排除这是否是 csrf 问题),我尝试包括 csrfmiddlewaretoken: '{{ csrf_token }}' 在 AJAX POST 请求(数据下方)中,这也没有解决问题。这是我的代码。

def profile_listview(request, username,
    template_name=userena_settings.USERENA_PROFILE_DETAIL_TEMPLATE,
    extra_context=None, **kwargs):
    user = get_object_or_404(get_user_model(),
                             username__iexact=username)
    fullsalelist = Entry.objects.filter(author__username__iexact=username)

    @csrf_exempt
    def delete_object(request):
        if request.is_ajax():
            print "request is ajax"
            object_name = request.POST.get('entryname')
            targetobject = Entry.objects.get(headline=object_name)
            if request.user.username == targetobject.author:
                targetobject.delete()
                print "hello" 
            return HttpResponseRedirect('/storefront/')

和AJAX模板中的代码:

<script type="text/javascript">
    var my_app = {
      username: "{{ request.user.username }}"  
    };
</script>

<script>
 $(document).ready(function() {
    $(".delete_button").click(function() {
        var id = $(this).attr('id');
        $.ajax({
            type: "POST",
            url: "/accounts/" + my_app.username + "/listview/",
            data: { entryname:id },
        });
        return false;
    });
});
</script>

网址

(r'^accounts/(?P<username>[\@\.\w-]+)/listview/$', profile_listview),

注意事项:

  1. 我在设置中开启了 csrf 中间件

  2. 在jQueryAJAX代码中,url和数据都发送了正确的信息

  3. 当我点击删除按钮时,出现 403 forbidden 错误。

  4. 打印 "request is ajax" 不会在控制台(或任何地方)打印。

我也很困惑,因为我得到的信息相互矛盾。有人告诉我应该通过 javascript (https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/) 添加 csrf 值。这给我留下了两个问题。 1. 这与在我的 POST 请求中添加 csrfmiddlewaretoken: '{{ csrf_token }}' 有什么不同?和 2. 更重要的是,我在使用 @csrf_exempt 时仍然收到 403 错误,这难道不是一个有争议的问题吗?

as catavaran认为你这叫错误观点。您应该调用 delete_object 视图。例如,添加 URL

(r'^accounts/(?P<username>[\@\.\w-]+)/listview/delete_object$', delete_object)

和AJAX

$.ajax({
        type: "POST",
        url: "/accounts/" + my_app.username + "/listview/delete_object",
        data: { entryname:id },
    });

希望对你有所帮助

据我了解,delete_object 是 profile_listview 中的一个函数,但 profile_listview 没有调用它。因此,profile_listview 没有 http 响应。 Post 错误信息

@csrf_exempt需要在urls.py调用的函数之前。在 OP 的示例中,delete_object 从未被调用,因为在调用没有装饰器的 profile_listview 时错误已经发生。

附带说明一下,如果 URL 不存在,可能会出现类似的情况(使用 @csrf_exempt 但得到 403)。出于某种原因(安全?),它将 return 403 而不是 404,因此很难调试。