koitaki (2) [Avatar] Offline
#1
With the Todo's application, when I went to add a new todo, I got this error:
CSRF verification failed. Request aborted.

It doesn't give much info on how to correct it.
The majority of advice given on StackOverflow suggested adding:
• {% csrf_token %} between the form tags
• context_instance=RequestContext(request)) as the 2nd argument in the render_to_response function.

However, with respect to the latter point, the book code doesn't use render_to_response, but uses instead HttpResponseRedirect(reverse(todo_index)), which doesn't seem to want to take the context_instance piece as a 2nd argument.

I've tried changing to the render_to_response function but no joy there either.

After a good while trying to find a solution, I've come here to seek advice for how to solve it. I've put the allegedly offending code below. Any suggestions?

Many thanks in advance!

def add_todo(request):
t = Todo(
title = request.POST['title'],
description = request.POST['description'],
importance = request.POST['importance'])
t.save()
# return HttpResponseRedirect(reverse(todo_index))
return render_to_response('index.tmpl',{'title': title, 'description': description, 'importance': importance},
context_instance=RequestContext(request))
koitaki (2) [Avatar] Offline
#2
Re: Chapter 8 Django CSRF Error (Listing 8.17)
Ok, after a fair bit of stumbling around, I've managed to no longer get the CSRF error. Next issue is that now I can't get any new Todo's to save. There are no warning messages, the runserver cmd screen shows a POST method, but nothing gets added to the database.

My current code for what I believe are the two relevant views:

def todo_index(request):
todos = Todo.objects.all().order_by('importance', 'title')
t = loader.get_template('index.tmpl')
c = Context({
'todos': todos,
'choices': importance_choices,
})
cs = {}
cs.update(csrf(c))
return render_to_response('index.tmpl', c, context_instance=RequestContext(request))

def add_todo(request):
t = Todo(
title = request.POST['title'],
description = request.POST['description'],
importance = request.POST['importance'])
t.save()
return HttpResponseRedirect(reverse(todo_index))

Any comments?
343340 (2) [Avatar] Offline
#3
I also had a CSRF Error when I attempted listing 8.16.

Following the instructions on the error page, I added a csrf token to index.tmpl:
<p>Add a todo:<br>
<form action="add" method="POST">{% csrf_token %}
	Todo:<input type="text" name="title"><br>
...

I also changed the Context in my index view to a RequestContext in views.py
def todo_index(request):
    todos = Todo.objects.all().order_by(
            'importance', 'title')
    t = loader.get_template('index.tmpl')
    c = RequestContext({'todos': todos,
                 'choices': importance_choices,
                 })
    return HttpResponse(t.render(c))

but that didn't work and I got a strange error that a "dict has no meta".
I tried many things, but finally read the Django documentation about the RequestContext https://docs.djangoproject.com/en/1.8/ref/templates/api/#subclassing-context-requestcontext and realized that the signature was different. One must pass the request object as well. This worked better:
 c = RequestContext(request, {'todos': todos,
                 'choices': importance_choices,
                 })


I had some other issues with my urls, but I think this is all that relates to the CSRF error.
343340 (2) [Avatar] Offline
#4
Re: Chapter 8 Django CSRF Error (Listing 8.17)
koitaki wrote:Ok, after a fair bit of stumbling around, I've managed to no longer get the CSRF error. Next issue is that now I can't get any new Todo's to save. There are no warning messages, the runserver cmd screen shows a POST method, but nothing gets added to the database.


That happened to me, too! After much blundering around, I found that changing the original project-level urls.py from the version given in listing 8.10 (I had just replaced todo.views.hello_world with the include)
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^.*', include(todo_urls)),  
] 

to the version in listing 8.15 (putting 'todos/' in the url string)
from todoApp import urls as todo_urls

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^todos/', include(todo_urls)),
]

magically solved the problem, though I don't know why.
RomanticStrings (3) [Avatar] Offline
#5
These solutions are not working for my app, which is being produced in Python 3.5.2/Django 1.10.1. I had to modify the entire procedure based upon the tutorial given on the Django Project page, since things have obviously changed since the book was produced. However, I fear that I have missed Hello! Python-specific details that don't match the tutorial page's project. Anyone had any success producing an updated project?
RomanticStrings (3) [Avatar] Offline
#6
I managed to solve the issue by changing my todo_index view to the following:

...
from django.template.loader import render_to_string
...
def todo_index(request):
    todos = Todo.objects.all().order_by(
        'importance', 'title')
    c = {'todos': todos,
         'choices': importance_choices}
    rendered = render_to_string('index.tmpl', c, request)
    return HttpResponse(rendered)