32

In Django template I used:

<form action="/user" method="post">{% csrf_token %}
    {{ form.as_p|safe }}
    <input type="submit" value="Submit" />
</form>

But error when I change to jinja2 template engine:

 Encountered unknown tag 'csrf_token'

My question: csrf_token protection in jinja2 is required?

If required, how to do this?

Thanks in advance!

Eddy Freddy
  • 1,820
  • 1
  • 13
  • 18
nguyên
  • 5,156
  • 5
  • 43
  • 45

7 Answers7

52

It seems Jinja2 works differently:

Use <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"> where in Django templates you use {% csrf_token %}

source : http://exyr.org/2010/Jinja-in-Django/

Guillaume Cisco
  • 2,859
  • 24
  • 25
36

I know this is an old question, but I wanted to update it with the proper way to support the csrf_token when using the new django.template.backends.jinja2.Jinja2 available in Django 1.8+. Using the django template backend you would have called {% csrf_token %}, but using the Jinja2 backend you will call it using {{ csrf_input }} (you can get just the token value instead of the token input using {{ csrf_token }}).

You can see the details in the django.template.backends.jinja2.Jinja2 source

lsowen
  • 3,728
  • 1
  • 21
  • 23
  • 2
    When using macros to render forms, for `csrf_input ` to be passed on, you'll need to import them with context e.g. `{% from "bootstrap/forms/horizontal.html" import render_form with context%}`. See [Jinja2 import visibility](http://jinja.pocoo.org/docs/dev/templates/#import-visibility) for more info. – Janusz Skonieczny Jan 19 '16 at 21:36
2

in django 2.x with jinja2 templates engine you get the value of the token with {{ csrf_token }} and the complete hidden input tag with {{ csrf_input }}

source: https://django.readthedocs.io/en/2.1.x/ref/csrf.html

example:

<form action="..." method="post">
  {{ csrf_input }}

   ...
</form>
0

I use Coffin. And have same problem when use:

from coffin.shortcuts import render_to_response
return render_to_response('template_name_here.html', context)

try to use instead:

from coffin.shortcuts import render
return render(request, 'template_name_here.html', context)
Vadim Zabolotniy
  • 347
  • 5
  • 16
0

You don't need to do anything special anymore. csrf_token is supported in django-jinja and works out of the box.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>test</title>
  </head>
  <body>
    <p>This should add a hidden input tag with the token. use it in your forms</p>
    {% csrf_token %}
  </body>
</html>
Emilio
  • 2,526
  • 22
  • 26
  • When I used it this way I got `("Encountered unknown tag 'csrf_token'. Jinja was looking for the following tags: 'endblock'. The innermost block that needs to be closed is 'block'.",)` error. – ruslaniv Jul 10 '20 at 11:42
  • 1
    That's strange. I'm using it.:
    {% csrf_token %} {{ form.as_p() }} ... Do you have the django_jinja.builtins.extensions.CsrfExtension properly listed in the settings.py, in the templates section?
    – Emilio Jul 10 '20 at 20:58
  • @Emilio Thanks for the comment. It is useful, but only when the template backend is `django_jinja`. – neuront Sep 20 '22 at 07:54
0

This peace of JS code can fix this, it will work for both Django and Jinja2, because it is pure javaScript handling for post method form tags, you can customize it by explore it friends

I'm just getting the CSRF token from cookies which already always exist and use it in form tags

let getCookie = (name) => {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}


$(()=>{
    formTags = document.querySelectorAll('[method="POST"]')
    
    let csrfToken = getCookie('csrftoken')

    

    Array.from(formTags).forEach(formTag=>{

        var inputTag = document.createElement('input')

        inputTag.setAttribute('type', 'hidden')
        inputTag.setAttribute('name', 'csrfmiddlewaretoken')
        inputTag.setAttribute('value', [csrfToken])
    
        formTag.appendChild(inputTag)

    })
})
-1

I had the same problem, and what I noticed is that the CSRF context processor isn't in the list of the default loaded processors. After adding 'django.core.context_processors.csrf' to the TEMPLATE_CONTEXT_PROCESSORS in setting.py I could use the {% csrf_token %} template tag normally.

Richard Otvos
  • 196
  • 1
  • 12