Шаблонные переменные Django и Javascript - PullRequest
179 голосов
/ 18 ноября 2008

Когда я отрисовываю страницу, используя шаблонизатор Django, я могу передать словарную переменную, содержащую различные значения, чтобы манипулировать ими на странице, используя {{ myVar }}.

Есть ли способ получить доступ к той же переменной в Javascript (возможно, используя DOM, я не знаю, как Django делает переменные доступными)? Я хочу, чтобы можно было искать детали, используя поиск AJAX на основе значений, содержащихся в переданных переменных.

Ответы [ 11 ]

251 голосов
/ 18 ноября 2008

{{variable}} подставляется непосредственно в HTML. Сделать вид источника; это не «переменная» или что-то подобное. Это просто отрисованный текст.

Сказав это, вы можете поместить такую ​​замену в свой JavaScript.

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

Это дает вам "динамический" JavaScript.

49 голосов
/ 28 августа 2014

ВНИМАНИЕ Проверьте тикет # 17419 для обсуждения добавления аналогичного тега в ядро ​​Django и возможных уязвимостей XSS, появившихся при использовании этого тега шаблона с данными, созданными пользователем. Комментарий от amacneil обсуждает большинство проблем, поднятых в билете.


Я думаю, что наиболее гибкий и удобный способ сделать это - определить шаблонный фильтр для переменных, которые вы хотите использовать в коде JS. Это позволяет вам гарантировать, что ваши данные правильно экранированы, и вы можете использовать их со сложными структурами данных, такими как dict и list. Вот почему я пишу этот ответ, несмотря на то, что есть принятый ответ с большим количеством голосов.

Вот пример шаблона шаблона:

// 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))

Этот шаблон фильтров преобразует переменную в строку JSON. Вы можете использовать его так:

// myapp/templates/example.html

{% load js %}

<script type="text/javascript">
    var someVar = {{ some_var | js }};
</script>
42 голосов
/ 13 декабря 2011

Решение, которое сработало для меня, заключается в использовании скрытого поля ввода в шаблоне

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

Затем получим значение в javascript таким образом,

var myVar = document.getElementById("myVar").value;
9 голосов
/ 07 августа 2013

Когда переменная возвращается Django, она превращает все кавычки в &quot;. Использование {{someDjangoVariable|safe}} вызывает ошибку Javascript.

Чтобы исправить это, используйте Javascript .replace:

<script type="text/javascript"> 
    var json = "{{someDjangoVariable}}".replace(/&quot;/g,"\"")
</script>
8 голосов
/ 20 ноября 2008

Для словаря лучше всего сначала кодировать в JSON. Вы можете использовать simplejson.dumps () или, если вы хотите преобразовать модель данных в App Engine, вы можете использовать encode () из библиотеки GQLEncoder.

6 голосов
/ 19 января 2019

Начиная с Django 2.1, новый встроенный тег шаблона был введен специально для этого варианта использования: json_script.

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

Новый тег безопасно сериализует значения шаблона и защищает от XSS.

6 голосов
/ 13 марта 2015

Вот что я делаю очень легко: Я изменил свой файл base.html для своего шаблона и поместил его внизу:

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

затем, когда я хочу использовать переменную в файлах javascript, я создаю словарь DJdata и добавляю его в контекст с помощью json: context['DJdata'] = json.dumps(DJdata)

Надеюсь, это поможет!

3 голосов
/ 10 ноября 2018

Я тоже с этим боролся. На первый взгляд кажется, что вышеприведенные решения должны работать. Однако архитектура django требует, чтобы каждый html-файл имел свои собственные отображаемые переменные (то есть {{contact}} отображается в contact.html, в то время как {{posts}} идет, например, index.html и т. Д.). С другой стороны, теги <script> появляются после {%endblock%} in base.html, от которого наследуются contact.html и index.html. В основном это означает, что любое решение, включая

<script type="text/javascript">
    var myVar = "{{ myVar }}"
</script>

обязательно завершится с ошибкой, поскольку переменная и сценарий не могут сосуществовать в одном и том же файле.

Простое решение, которое я в конце концов придумал и сработало для меня, заключалось в том, чтобы просто обернуть переменную тегом id и позже обратиться к нему в файле js, например:

// index.html
<div id="myvar">{{ myVar }}</div>

, а затем:

// somecode.js
var someVar = document.getElementById("myvar").innerHTML;

и просто включите <script src="static/js/somecode.js"></script> в base.html как обычно. Конечно, это всего лишь получение контента. Что касается безопасности, просто следуйте другим ответам.

3 голосов
/ 07 октября 2015

Я сталкивался с подобной проблемой, и ответ, предложенный С. Лоттом, работал на меня.

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

Однако я хотел бы указать основное ограничение реализации здесь. Если вы планируете поместить свой код JavaScript в другой файл и включить этот файл в свой шаблон. Это не сработает.

Это работает только тогда, когда вы используете основной шаблон и код JavaScript в одном файле. Вероятно, команда django может устранить это ограничение.

1 голос
/ 07 марта 2017

Для объекта JavaScript, хранящегося в поле Django в виде текста, который должен снова стать объектом JavaScript, динамически вставляемым в сценарий на странице, необходимо использовать как escapejs, так и JSON.parse():

var CropOpts = JSON.parse("{{ profile.last_crop_coords|escapejs }}");

Django escapejs правильно обрабатывает кавычки, а JSON.parse() преобразует строку обратно в объект JS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...