Подтвердить что ты не робот

Передача данных Python в JavaScript через Django

Я использую Django и Apache для обслуживания веб-страниц. В моем JavaScript-коде в настоящее время включен объект данных со значениями, которые будут отображаться в различных виджетах HTML, на основе выбора пользователя из меню вариантов. Я хочу получить эти данные из словаря Python. Я думаю, что я знаю, как встраивать код JavaScript в HTML, но как я могу вставлять объект данных в этот script ( "на лету" ), чтобы функции script могли его использовать?

Другими словами, я хочу создать объект или массив JavaScript из словаря Python, затем вставить этот объект в код JavaScript, а затем вставить этот код JavaScript в HTML.

Я полагаю, что эта структура (например, данные, встроенные в переменные в код JavaScript) является субоптимальной, но как новичок я не знаю альтернатив. Я видел записи о функциях сериализации Django, но они не помогают мне, пока я не получу данные в свой код JavaScript в первую очередь.

Я пока не использую библиотеку JavaScript, такую ​​как jQuery.

4b9b3361

Ответ 1

нотабене см. обновление 2018 года внизу

Я рекомендую не добавлять много JavaScript в ваши шаблоны Django - его сложно писать и отлаживать, особенно по мере расширения вашего проекта. Вместо этого попробуйте написать весь свой JavaScript в отдельном файле сценария, который загружает ваш шаблон, и просто включить в шаблон только объект данных JSON. Это позволяет вам выполнять такие вещи, как запускать все ваше приложение JavaScript через что-то вроде JSLint, минимизировать его и т.д., И вы можете протестировать его в статическом HTML файле без каких-либо зависимостей в вашем приложении Django. Использование библиотеки, такой как simplejson, также экономит время, затрачиваемое на написание утомительного кода сериализации.

Если вы не предполагаете, что создаете приложение AJAX, это может быть сделано просто так:

По мнению:

from django.utils import simplejson


def view(request, …):
    js_data = simplejson.dumps(my_dict)
    …
    render_template_to_response("my_template.html", {"my_data": js_data, …})

В шаблоне:

<script type="text/javascript">
    data_from_django = {{ my_data }};
    widget.init(data_from_django);
</script>

Обратите внимание, что тип данных имеет значение: если my_data является простым числом или строкой из контролируемого источника, который не содержит HTML, например форматированной даты, никакой специальной обработки не требуется. Если есть возможность получить ненадежные данные, предоставленные пользователем, вам необходимо очистить их с помощью фильтров типа escape или escapejs и убедиться, что ваш JavaScript обрабатывает данные безопасно, чтобы избежать межсайтовый скриптинг атак.

Что касается дат, вы можете подумать о том, как вы проводите даты. Мне почти всегда было проще передать их как метки времени Unix:

В Джанго:

time_t = time.mktime(my_date.timetuple())

В JavaScript, если вы сделали что-то вроде time_t = {{ time_t }} с результатами приведенного выше фрагмента:

my_date = new Date();
my_date.setTime(time_t*1000);

Наконец, обратите внимание на UTC - вам нужно, чтобы функции даты Python и Django обменивались данными в UTC, чтобы избежать смущающих сдвигов по местному времени пользователя.

ОБНОВЛЕНИЕ: Обратите внимание, что setTime в javascript находится в миллисекундах, тогда как вывод time.mktime равен секундам. Вот почему нам нужно умножить на 1000

Обновление 2018 года. Мне по-прежнему нравится JSON для сложных значений, но за прошедшее десятилетие API данных HTML5 достиг почти универсальной поддержки браузера, и это очень удобно для передачи простых (non-list/dict), особенно если вы хотите, чтобы правила CSS применялись на основе этих значений, и вам не нужны неподдерживаемые версии Internet Explorer.

<div id="my-widget" data-view-mode="tabular">…</div>

let myWidget = document.getElementById("my-widget");
console.log(myWidget.dataset.viewMode); // Prints tabular
somethingElse.addEventListener('click', evt => {
    myWidget.dataset.viewMode = "list";
});

Это отличный способ представить данные в CSS, если вы хотите установить начальное состояние просмотра в шаблоне Django и автоматически обновлять его, когда JavaScript обновляет атрибут data-. Я использую это для таких вещей, как скрытие виджета прогресса, пока пользователь не выберет что-либо для обработки или для условного отображения/скрытия ошибок на основе результатов выборки или даже для чего-то вроде отображения количества активных записей с использованием CSS, например #some-element::after { content: attr(data-active-transfers); }.

Ответ 2

Для тех, у кого могут возникнуть проблемы с этим, убедитесь, что вы создаете объект json в безопасном режиме в шаблоне. Вы можете вручную установить это следующим образом:

<script type="text/javascript">
    data_from_django = {{ my_data|safe }};
    widget.init(data_from_django);
</script>

Ответ 3

Вы можете включать теги <script> внутри ваших .html-шаблонов, а затем создавать свои структуры данных, но это удобно для вас. Язык шаблона не только для HTML, но и для литералов объектов Javascript.

И Павел прав: лучше было бы использовать json-модуль для создания строки JSON, а затем вставить эту строку в шаблон. Это будет лучше справляться с проблемами цитирования и с легкостью справляться с глубокими структурами.

Ответ 4

Это субоптимально. Рассматривали ли вы передачу данных как JSON, используя для этого django, встроенный в сериализатор?

Ответ 5

Начиная с середины 2018 года, самый простой подход - использовать JSON-модуль Python, теперь simplejson устарел. Помните, что, как упоминает @wilblack, вам нужно предотвратить автоэкранирование Django, используя фильтр safe или тег autoescape с опцией off. В обоих случаях в представлении вы добавляете содержимое словаря в контекст

viewset.py

import json
 def get_context_data(self, **kwargs):
    context['my_dictionary'] = json.dumps(self.object.mydict)

а затем в шаблоне, который вы добавляете, как предложил @wilblack:

template.html

<script>
    my_data = {{ my_dictionary|safe }};
</script>

Ответ 6

См. ответ на этот вопрос. Один из вариантов заключается в использовании jsonpickle для сериализации между объектами Python и объектами JSON/Javascript. Он обертывает simplejson и обрабатывает вещи, которые обычно не принимаются simplejson.

Ответ 7

Вставка Java Script, встроенного в шаблон Django, скорее всегда плохая идея.

Скорее, поскольку из этого правила есть некоторые исключения.

Все зависит от вашего сайта и функциональности вашего сайта Java Script.

Лучше иметь отдельные статические файлы, такие как JS, но проблема в том, что каждому отдельному файлу нужен еще один механизм connect/GET/request/response. Иногда для небольшого, два лайнера кода os JS, чтобы поместить это в шаблон, bun затем использовать механизм django templatetags - вы можете использовать это в других шаблонах;)

Об объектах - то же самое. Если ваш сайт имеет структуру AJAX/web2.0, например, пользу - вы можете добиться очень хорошего эффекта, добавив некоторую операцию count/math на клиентскую сторону. Если объекты невелики - встроены в шаблон, если они большие - откликните их в другом соединении, чтобы избежать загрузки страницы для пользователя.