Шаблон Django - Преобразование списка Python в объект JavaScript
Я работаю над сайтом Django / Python. У меня есть страница, где я хочу отобразить таблицу результатов поиска. Список результатов передается в шаблон как обычно.
Я также хочу сделать этот список объектов доступным для кода JavaScript.
Моим первым решением было просто создать другое представление, возвращающее формат JSON. Но каждая загрузка страницы требовала вызова запроса дважды. Тогда я попытался только загрузить данные, используя представление JSON, и распечатать таблицу, используя JavaScript.
Но это также нежелательно, так как теперь слой представления смешан с кодом JavaScript.
Есть ли способ создать объект JavaScript из списка Python при визуализации страницы?
4 ответа
Решение
Я создал собственный шаблонный фильтр, см. Пользовательские шаблонные теги и фильтры.
from django.core.serializers import serialize
from django.db.models.query import QuerySet
from django.utils import simplejson
from django.utils.safestring import mark_safe
from django.template import Library
register = Library()
def jsonify(object):
if isinstance(object, QuerySet):
return mark_safe(serialize('json', object))
return mark_safe(simplejson.dumps(object))
register.filter('jsonify', jsonify)
jsonify.is_safe = True
Вызовы mark_safe важны. В противном случае Джанго избежит этого.
В шаблоне:
//Without template filter (you'll need to serialise in the view)
var data = jQuery.parseJSON('{{ json_data|safe }}');
alert(data.length);
//Using the template filter
var data2 = jQuery.parseJSON('{{ record_list|jsonify }}');
alert(data2.length);
Обратите внимание на одинарные кавычки вокруг тега шаблона.
Хотя мой следующий вопрос будет - это действительно безопасно?
Обновить
Обновленная версия, работающая в django 1.8 вышеуказанного тега шаблона, которая также обрабатывает передаваемый список плоских значений, т.е. values_list('myfield', flat=True):
from django.core.serializers import serialize
from django.db.models.query import QuerySet, ValuesListQuerySet
from django.template import Library
import json
register = Library()
@register.filter( is_safe=True )
def jsonify(object):
if isinstance(object, ValuesListQuerySet):
return json.dumps(list(object))
if isinstance(object, QuerySet):
return serialize('json', object)
return json.dumps(object)
Новое в Django 2.1: json_script
В Django 2.1 появился новый тег шаблона: json_script
, Это почти то, что вы ищете, может быть, даже лучше. Он преобразует значение Python в JSON, завернутый в <script>
тег. Итак, этот шаблон:
{{ value|json_script:"foobar" }}
... будет производить это:
<script id="foobar" type="application/json">{"example": "example"}</script>
Это не нормальный Javascript <script>
тег, он не работает, это просто JSON. Если вы хотите получить доступ к содержимому вашего Javascript, вы можете сделать это следующим образом:
var value = JSON.parse(document.getElementById('foobar').textContent);
Этот тег был закодирован так, что он правильно экранирован, строка с </script>
в этом ничего не сломается, например.
Как насчет фильтра, который выводит значение Python в JSON? Вот пример реализации:
http://djangosnippets.org/snippets/201/
Поскольку значение JSON также является допустимой правой частью для назначения Javascript, вы можете просто поместить что-то вроде...
var results = {{results|jsonify}};
внутри вашего сценария.
Посмотри и этот ответ тоже.
Но это не способ высокой нагрузки. Вы должны:
а) Создать JSON-файлы, поместить на диск или S3. В случае, если JSON статический
б) Если JSON является динамическим. Создайте JSON по отдельному URL (например, API) в вашем приложении.
И загрузить в JS напрямую в любом случае. Например:
$.ajax('/get_json_file.json')
PS: простите за мой английский.