djangorendercsrfrender-to-response

Django - CSRF Token generation - render_to_response vs render


I am trying out a simple user registration form in Django. CSRF token is not getting generated when I use render_to_response

return render_to_response('registration/register.html', RequestContext(request, {'form': RegistrationForm()}))

where as, CSRF token is getting generated when I use render

return render(request, 'registration/register.html', {'form':RegistrationForm()})

Am I doing anything wrong with render_to_response

Following is the relevant code block

views.py

@csrf_protect
def register(request):
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            user = User.objects.create_user(
                username=form.cleaned_data['username'],
                password=form.cleaned_data['password1'],
                email=form.cleaned_data['email']
            )
            return HttpResponseRedirect('/register_success/')
    else:
        return render_to_response('registration/register.html', RequestContext(request, {'form': RegistrationForm()}))

register.html

{% extends "base.html" %}
{% block title %}User Registration{% endblock %}

{% block content %}
    <form method="post" action=".">
        {% csrf_token %}
        <table border="0">
            {{ form.as_table }}
        </table>
        <input type="submit" value="Register" />
    </form>
{% endblock %}

Solution

  • The recommended approach is to use render instead of render_to_response. The code is simpler, and the CSRF token will work because render will uses a request context to render the template.

    return render(request, 'registration/register.html', {'form': RegistrationForm()})
    

    The docs recommend that you don't use render_to_response. Before Django 1.10, you could manually pass a RequestContext as the third argument, but this is not possible in Django 1.10+. You are using a RequestContext as the second argument which is incorrect - the second argument should be a regular dictionary.

    Finally, note that you are not returning a response when the form is invalid. You could fix this by adjusting your code slightly:

    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            ...
            return HttpResponseRedirect('/register_success/')
    else:
        form = RegistrationForm()
    return render(request, 'registration/register.html', {'form': form})