djangoviewdjango-csrf

Django: POST form requires CSRF? GET doesn't?


Are forms that use the POST method required to have CSRF protection? I'm following a book and the code examples throw 403 errors. I did some searching and it seems as if I need to enable CSRF in all my forms.

My questions are:

  1. Does Django now require that all POST forms be protected from CSRF?

  2. All I need to do to accomplish this is add django.middleware.csrf.CsrfViewMiddleware, return render_to_response(template,dictionary, context_instance=RequestContext(request), and add {% csrf_token %} in the corresponding form? Am I missing anything here?

When I do this, the form works fine. When any of these pieces are missing, it fails to 403. I just want to make sure I'm doing it RIGHT. :)

Thanks in advance.

edit:

For some reason this code doesn't make sense to me but it doesnt return any error. Please ignore the primitive validation as I haven't gotten to the section of the book where it shows the more efficient way to do it yet.

def contact(request):
    errors = []
    if request.method == 'POST':
        if not request.POST.get('subject', ''):
            errors.append('Enter a subject')
        if not request.POST.get('message', ''):
            errors.append('Enter a message')
        if request.POST.get('email', '') and '@' not in request.POST['email']:
            errors.append('Enter a valid email address')
        if not errors:
            send_mail(
                request.POST['subject'],
                request.POST['message'],
                request.POST.get('email', 'noreply@example.com'),
                ['siteownder@example.com'],
            )
            return HttpResponseRedirect('/contact/thanks/')
    return render_to_response(
        'contact_form.html', 
        {'errors': errors}, 
        context_instance=RequestContext(request),
    )

My issue is with the very last line of this view function. It is only called if the request.method != 'POST'. This seems completely wrong to me. Shouldn't I be calling context_instance=RequestContext(request) when it's doing a POST?


Solution

  • POST should be used for sensitive information, such as passwords, and django requires securing it with csrf_token; GET should be used for bookmarkable stuff which doesn't need to be secured, like searches. You ARE doing it RIGHT.

    EDIT

    You shouldn't be calling context_instance=RequestContext(request) when it's doing a POST, you should be calling it regardless of the request type. Look at it like this:

    Actions in italic are done by the last return, regardless of the if.