Search code examples
pythondjangodjango-rest-frameworkcsrfdjango-csrf

Django CSRF token is missing from signup form


I have another problem caused by the major upgrades I've done to a Django app (from 1.7 to 1.10 and Django Rest Framework to 3.5.4). I managed to fix some other errors that were causing a 500 error on the signup page, but still I have a problem with the CSRF token. This functionality was working before the upgrades. I have checked all the things mentioned in the error paged (I have DEBUG=True), but all of them seem ok, as to follow:

In the class "CompanyAdmin" I have the signup method:

def signup(self, request):
    if request.method == "GET":
        form = SignupForm()
    else:
        form = SignupForm(request.POST)

        if form.is_valid():
            company = form.save()
            user = company.managers.all()[0]
            user = authenticate(
                email=user.email, password=request.POST["password1"])
            if user is not None:
                login(request, user)
                return HttpResponseRedirect(reverse("bagdisken:index"))

    return shortcuts.render_to_response("bagdisken/signup.html",
                                        context=RequestContext(request, {
                                            'form': form,
                                        }))

I had problems with the context, causgin a 500 error, which I fixed by adding the request in the context. Previous it was like this:

return shortcuts.render_to_response("bagdisken/signup.html", {'form': form})

The CSRF token is present in the view:

{% extends "admin/base_site.html"%}
{% load form_utils %}
{% block content_title%}{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block nav-global %}{% endblock %}
{% block coltype %}twelve columns offset-by-two{% endblock %}
{% block content%}
    <form id="signup" action="#" method="POST" >
        {% csrf_token %}
            {{ form|render }}
            <input type="submit" value="Submit" />
    </form>
{% endblock %}

And the CsrfViewMiddleware is also present in setting:

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'corsheaders.middleware.CorsMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

Still, the hidden input for the csrf token is absent. How can I fix the problem?


Solution

  • Don't use render_to_response, it's obsolete. It doesn't make the request available in the response, so the CSRF template context processor does not work.

    Use the render shortcut instead. It renders the template with a request, so the CSRF token will work.

    from django.shortcuts import render
    
    def signup(self, request):
        ...
        return render(request, "bagdisken/signup.html", {'form': form})