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_token 用于单个页面上的多个表单和 ajax 请求