Django 评论 - Ajax 和 CSRF 失败

Posted

技术标签:

【中文标题】Django 评论 - Ajax 和 CSRF 失败【英文标题】:Django comments - Ajax and CSRF failure 【发布时间】:2011-09-28 16:37:35 【问题描述】:

我认为这与这里的其他问题不同,我已经检查了答案,但仍然没有运气。感谢您的帮助:

我有一个新闻项目列表(如 facebook 提要),每个项目都附有评论表(使用 django.contrib.cmets 应用程序)。可以正常使用。

但是,我在页面上使用了一种 AJAX“无限滚动”——当您滚动时,它会通过 AJAX 加载下一组新闻项目和相关评论表单。新加载的新闻项目的评论表单不起作用(CSRF 验证失败)。

原因很明显 - % csrf_token % 没有传递给返回的 JSON 响应,因此新加载的评论表单没有 CSRF 数据。

我尝试在 Django 页面 (https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax) 上使用 set cookie 方法,但似乎没有用,也没有确实尝试使用 @csrf_exempt 装饰器来完全排除 CSRF。

有什么建议可以将 csrf_token 与返回的 JSON 响应一起传递吗?或者有其他选择吗?

这是视图:

def my_view(request):
    # the normal view gets a queryset of all Info items and returns them
    infos = Info.objects.all()
    ....

    # here's the AJAX part
    if request.GET.get('xhr') and page > 1:
        infos = paginator.page(int(request.GET.get('page')))
        objects_list = []
        for object in infos:
            objects_list.append(render_to_string('list/snippets/feed_li.html', 
                'object': object,
            ))

        json =  simplejson.dumps(objects_list, cls=DjangoJSONEncoder)
        return HttpResponse(json, mimetype='application/json')

【问题讨论】:

【参考方案1】:

一种选择是通过您返回的 JSON 响应向您的表单提供 CSRF 令牌。我相信您可以通过调用 django.middleware.csrf.get_token(request) 以编程方式获取 CSRF 令牌,然后将该值包含在您的 ajax 响应中。

我能想到的另一个选项是禁用该视图的 CSRF 保护。

【讨论】:

【参考方案2】:

首先检查您是否忘记在 'list/sn-ps/feed_li.html' 中包含 % csrf_token %;

其次,要使csrf令牌正常工作,必须使用RequestContext或手动生成令牌并在渲染模板时将其添加到上下文变量中(参见Django csrf ref)。因此,替换行:

objects_list.append(render_to_string('list/snippets/feed_li.html', 
    'object': object,
))

与:

''' from django.template import RequestContext ''' 
objects_list.append(render_to_string('list/snippets/feed_li.html', \
    RequestContext(request, 'object':object)
))

或:

''' from django.core.context_processors import csrf '''
vars = 
vars.update(csrf(request))
vars.update('object':object)
objects_list.append(render_to_string('list/snippets/feed_li.html', vars))

【讨论】:

以上是关于Django 评论 - Ajax 和 CSRF 失败的主要内容,如果未能解决你的问题,请参考以下文章

Django与CSRF AJAX

带有ajax和django post的csrf

django:csrf_token 用于单个页面上的多个表单和 ajax 请求

Django - 在同一个模板(ajax 和表单)中处理多个 CSRF 令牌禁止(CSRF 令牌丢失或不正确。)

第六章:Django 综合篇 - 17:CSRF与AJAX

第六章:Django 综合篇 - 17:CSRF与AJAX