0
votes

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

2 Answers

0
votes

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.

0
votes

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