Django 评论 - Ajax 和 CSRF 失败

发布于 2024-11-18 15:27:03 字数 1141 浏览 2 评论 0原文

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

我有一个新闻项目列表(例如 Facebook feed),并且每个项目都附有一个评论表(使用 django.contrib.comments 应用程序)。正常情况下工作正常。

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

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

我已经尝试在 Django 页面上使用 set cookie 方法(https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax),但似乎不起作用,也没有尝试@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')

I think this is different to other problems here, I've checked out answers and still no luck. Thanks for any help:

I have a list of News items (like a facebook feed) and there's a comment form attached to each one (using the django.contrib.comments app). It works fine normally.

BUT, I'm using a kind of AJAX 'infinite scroll' on the page - as you scroll, it loads the next set of News items and related comment form via AJAX. The comment forms on the newly-loaded news items don't work (it fails on CSRF validation).

It's obvious why - the {% csrf_token %} isn't passed to the JSON response that comes back, so the newly-loaded comment forms have no CSRF data.

I've tried using the set cookie method on the Django pages (https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax), but doesn't seem to work and neither does trying the @csrf_exempt decorator to totally exclude CSRF.

Any suggestions how I can pass a csrf_token along with the returning JSON response? Or is there an alternative?

Here's the view:

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')

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

初心 2024-11-25 15:27:03

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

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

One option is going to be to provide the CSRF token to your form via the JSON response you are returning. I believe you can get the CSRF token programatically by calling django.middleware.csrf.get_token(request) and then including that value in your ajax response.

The other option I can think of is to disable the CSRF protection for that view.

秋凉 2024-11-25 15:27:03

首先检查一下您是否忘记在“list/snippets/feed_li.html”中包含 {% csrf_token %};

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

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))

First check out if you forgot to include {% csrf_token %} in the 'list/snippets/feed_li.html';

Second, to make the csrf token function properly, you must use RequestContext or manually generate the token and add it to the context variable when rendering the template(see Django csrf ref). Thus, replace the line:

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

with:

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

or:

''' 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))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文