Django Template Variables and Javascript

295,593

Solution 1

The {{variable}} is substituted directly into the HTML. Do a view source; it isn't a "variable" or anything like it. It's just rendered text.

Having said that, you can put this kind of substitution into your JavaScript.

<script type="text/javascript"> 
   var a = "{{someDjangoVariable}}";
</script>

This gives you "dynamic" javascript.

Solution 2

CAUTION Check ticket #17419 for discussion on adding similar tag into Django core and possible XSS vulnerabilities introduced by using this template tag with user generated data. Comment from amacneil discusses most of the concerns raised in the ticket.


I think the most flexible and handy way of doing this is to define a template filter for variables you want to use in JS code. This allows you to ensure, that your data is properly escaped and you can use it with complex data structures, such as dict and list. That's why I write this answer despite there is an accepted answer with a lot of upvotes.

Here is an example of template filter:

// myapp/templatetags/js.py

from django.utils.safestring import mark_safe
from django.template import Library

import json


register = Library()


@register.filter(is_safe=True)
def js(obj):
    return mark_safe(json.dumps(obj))

This template filters converts variable to JSON string. You can use it like so:

// myapp/templates/example.html

{% load js %}

<script type="text/javascript">
    var someVar = {{ some_var | js }};
</script>

Solution 3

A solution that worked for me is using the hidden input field in the template

<input type="hidden" id="myVar" name="variable" value="{{ variable }}">

Then getting the value in javascript this way,

var myVar = document.getElementById("myVar").value;

Solution 4

As of Django 2.1, a new built in template tag has been introduced specifically for this use case: json_script.

https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#json-script

The new tag will safely serialize template values and protects against XSS.

Django docs excerpt:

Safely outputs a Python object as JSON, wrapped in a tag, ready for use with JavaScript.

Solution 5

Here is what I'm doing very easily: I modified my base.html file for my template and put that at the bottom:

{% if DJdata %}
    <script type="text/javascript">
        (function () {window.DJdata = {{DJdata|safe}};})();
    </script>
{% endif %}

then when I want to use a variable in the javascript files, I create a DJdata dictionary and I add it to the context by a json : context['DJdata'] = json.dumps(DJdata)

Hope it helps!

Share:
295,593

Related videos on Youtube

Arya V Nair
Author by

Arya V Nair

Updated on December 15, 2020

Comments

  • Arya V Nair
    Arya V Nair over 3 years

    When I render a page using the Django template renderer, I can pass in a dictionary variable containing various values to manipulate them in the page using {{ myVar }}.

    Is there a way to access the same variable in Javascript (perhaps using the DOM, I don't know how Django makes the variables accessible)? I want to be able to lookup details using an AJAX lookup based on the values contained in the variables passed in.

  • Casebash
    Casebash almost 14 years
    Note though that according to this solution, this is vulnerable to injection attacks
  • Tomasz Zieliński
    Tomasz Zieliński over 12 years
    @Casebash: For such occasions escapejs filter exists: escapejs('<>') -> u'\\u003C\\u003E'
  • Mark
    Mark over 12 years
    Just to add on to this for reference: if the "someDjangoVariable" so happens to be JSON, be sure to use {{ someDjangoVariable|safe }} to remove the &quot;
  • AndyL
    AndyL about 12 years
    be wary though. depending on how you use the variable/form, the user could put in whatever they want.
  • nu everest
    nu everest over 11 years
    you may also want to set your input field to readonly (see this link w3schools.com/tags/att_input_readonly.asp)
  • Mikhail
    Mikhail about 11 years
    Additionally make sure that the string isn't broken into multiple lines.
  • Mario
    Mario over 9 years
    Does anyone know of a "gon" (github.com/gazay/gon) equivalent for Django?
  • Alan Evangelista
    Alan Evangelista over 9 years
    This answer only works for a simple variable, it does not work for a complex data structure. In this case, the simplest solution is to add client-side code to traverse the data structure and build a similar one in Javascript. If the complex data structure is in JSON format, another solution is to serialize it, pass a serialized JSON to the Django template in server-side code and deserialize the JSON in a javascript object in client-side code. One answer below mentions this alternative.
  • Alan Evangelista
    Alan Evangelista over 9 years
    That is nice because it allows copying only some Django template input variables to Javascript and server-side code does not need to know which data structures must be used by Javascript and hence converted to JSON before rendering the Django template. Either use this or always copy all Django variables to Javascript.
  • w0rp
    w0rp about 9 years
    Please update this to include the |escapejs filter, otherwise you can end up with variables containing quote characters in the name and such, and this can lead to XSS attacks.
  • user1496984
    user1496984 almost 9 years
    So the best solution is to use var a = {{someDjangoVariable|escapejs|safe}}" then?
  • fiveclubs
    fiveclubs over 8 years
    Note that 'simplejson' became 'json' as of django 1.7, I believe.
  • James111
    James111 over 8 years
    If it's something that won't alter a database or won't be sent to a database query this would be fine. @AndyL
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com almost 8 years
  • the_unknown_spirit
    the_unknown_spirit over 7 years
    what if the javascript is written in a different file?
  • user2867288
    user2867288 about 7 years
    Guys... users can do what they want anyways. Browsers make it so easy nowadays with a fully featured DOM inspector and debugging tools. Moral of the story: do ALL you data validation on the server.
  • Jorge Orpinel Pérez
    Jorge Orpinel Pérez almost 7 years
    Nice. Is that the same as just using docs.djangoproject.com/en/1.10/ref/templates/builtins/#safe though?
  • Yaroslav Admin
    Yaroslav Admin almost 7 years
    @JorgeOrpinel No, it is not same. safe only marks value as safe, without proper conversion and escaping.
  • kbdev
    kbdev almost 7 years
    How do you then display the variable in the django template?
  • Ahtisham
    Ahtisham over 6 years
    Please can anyone tell me how would you access that variable in an external JavaScript file ? but a secure way.
  • Ahtisham
    Ahtisham over 6 years
    Please can anyone tell me how would you access that variable in an external JavaScript file ?
  • Sahand
    Sahand over 6 years
    Ahtisham, you get it by doing what bosco- did: var myVar = document.getElementById("myVar").value;. This will work if the javascript is executed on the same page as the hidden input element.
  • Sahand
    Sahand over 6 years
    @YaroslavAdmin, isn't it a problem that this solutions requires one to always keep the javascript in the template file? Most of the projects I've seen keeps the javascript in a separate js-folder. I tried you solution and it doesn't work with the js in a separate folder.
  • Yaroslav Admin
    Yaroslav Admin over 6 years
    @Sandi back when I posted it it was common to have a widget in separate JS file and initialize it in the page source code. So let's say you declare function myWidget(config) { /* implementation */ } in JS file and than you use it on some pages using myWidget({{ pythonConfig | js }}). But you can not use it in JS files (as you noticed), so it has its limitations.
  • Jon Sakas
    Jon Sakas over 5 years
    10 years later and Django has introduced a built in template filter just for this: docs.djangoproject.com/en/2.1/ref/templates/builtins/…
  • Mohith7548
    Mohith7548 almost 5 years
    I have Django template for creating a button with id in html tag = name of the object id="{{ obj.name }}. Now how to refer to this id by JS? Doing this is giving me error. var c = document.getElementById({{ obj.name }});
  • pcworld
    pcworld over 4 years
    Don't use this, it's vulnerable to XSS (script injection). For instance an attacker could inject </script> into the data, thus breaking out of the current script and injecting arbitrary HTML (including starting a new script with <script>).
  • pcworld
    pcworld over 4 years
    Don't use this, it's vulnerable to script injection (XSS).
  • derteufelqwe
    derteufelqwe over 3 years
    This should actually be the answer. This works perfectly without any weired manual quote escaping.
  • logicOnAbstractions
    logicOnAbstractions almost 3 years
    Best answer in 2021 overall. Jon Saks provided the same however didn't include actual code in the answer, only links to docs (links break, change, move....)
  • Yi Zong Kuang
    Yi Zong Kuang over 2 years
    If you have double quotes or single quotes in your someDjangoVariable, it's better to do this var a = `{{someDjangoVariable|safe}}`;. Or if it's JSON content in your someDjangoVariable, it's might be best to just do var a = {{someDjangoVariable|safe}};, this way Javascript will load the JSON correctly