Search code examples
pythonhtmldjangodjango-templatespythonanywhere

Disappearing {% csrf_token %} on website file


When I wanted use my registration form in my site, I get ERROR 403: "CSRF verification failed. Request aborted." In source of this website I realised that is missing. This is part of view-source from my site:

<div style="margin-left:35%;margin-right:35%;">
<fieldset>
<legend> Wszystkie pola oprócz numeru telefonu należy wypełnić </legend>
    <form method="post" action=".">
        <p><label for="id_username">Login:</label> <input id="id_username" maxlength="30" name="username" type="text" required/></p>
<p><label for="id_email">Email:</label> <input id="id_email" name="email" type="email" required /></p>
<p><label for="id_password1">Hasło:</label> <input id="id_password1" name="password1" type="password" required /></p>
<p><label for="id_password2">Powtórz hasło:</label> <input id="id_password2" name="password2" type="password" required /></p>
<p><label for="id_phone">Telefon:</label> <input id="id_phone" maxlength="20" name="phone" type="text" /></p>
<p><label for="id_log_on">Logowanie po rejestracji:</label><input id="id_log_on" name="log_on" type="checkbox" /></p>
        <input type="submit" value="Rejestracja"><input type="reset" value="Wartości początkowe">
    </form>
</fieldset>
</div>

I was surprised of that, because in my files on Pythonanythere this fragment of code is present.

This is part of my file register.html on Pythonanythere:

<div style="margin-left:35%;margin-right:35%;">
<fieldset>
<legend> Wszystkie pola oprócz numeru telefonu należy wypełnić </legend>
    <form method="post" action=".">{% csrf_token %}
        {{ form.as_p }}
        <input type="submit" value="Rejestracja"><input type="reset" value="Wartości początkowe">
    </form>
</fieldset>
</div>

What am I doing wrong that my webpage don't see this piece of code? It is seamed on server but on webpage view-source It isn't.

EDIT: This is view, which render my template:

def register(request):
    if request.method == 'POST':
    form = FormularzRejestracji(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']
        )
        user.last_name = form.cleaned_data['phone']
        user.save()
        if form.cleaned_data['log_on']:
            user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password1'])
            login(request, user)
            template = get_template("osnowa_app/point_list.html")
            variables = RequestContext(request, {'user': user})
            output = template.render(variables)
            return HttpResponseRedirect("/")
        else:
            template = get_template("osnowa_app/register_success.html")
            variables = RequestContext(request, {'username': form.cleaned_data['username']})
            output = template.render(variables)
            return HttpResponse(output)

else:
    form = FormularzRejestracji()
template = get_template("osnowa_app/register.html")
form = FormularzRejestracji()
variables = RequestContext(request, {'form': form})
output = template.render(variables)
return HttpResponse(output)

Solution

  • You should pass a plain dict and the request object to template.render(), not a RequestContext. The template engine will convert it to a RequestContext for you:

    template = get_template("osnowa_app/register.html")
    context = {'form': form}
    output = template.render(context, request)
    

    Right now, the template.render() function sees a dict-like object as the first argument, but no request as the second argument. Without a request as the second argument, it converts the dict-like RequestContext into a plain Context object. Since the Context object doesn't run context processors, your context is missing the csrf token.

    Alternatively you can just use the render shortcut, which returns a HttpResponse object with the rendered template as content:

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

    This particular case is also being discussed in ticket #27258.