Plantilla Django – Convertir una lista de Python en un objeto de JavaScript

Estoy trabajando en un sitio web de Django / Python. Tengo una página donde quiero mostrar una tabla de resultados de búsqueda. La lista de resultados se pasa a la plantilla como de costumbre.

También quiero hacer esta lista de objetos accesibles al código JavaScript.

Mi primera solución fue crear otra vista que devolviera el formato JSON . Pero cada carga de página requiere llamar a la consulta dos veces. Entonces intenté solo descargar los datos utilizando la vista JSON e imprimir la tabla utilizando JavaScript.

Pero esto tampoco es deseable ya que ahora la capa de presentación se mezcla con el código JavaScript.

¿Hay alguna forma de crear un objeto JavaScript desde la lista de Python a medida que se representa la página?

¿Qué tal un filtro que descarga un valor de Python a JSON? Aquí hay una implementación de ejemplo:

http://djangosnippets.org/snippets/201/

Dado que un valor JSON también es un lado derecho válido para una asignación de Javascript, simplemente puede poner algo como …

var results = {{results|jsonify}}; 

dentro de su guión.

Solución

Creé un filtro de plantillas personalizadas, veo tags y filtros de plantillas personalizadas .

 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 

Las llamadas a mark_safe son importantes. De lo contrario Django lo escapará.

En la plantilla:

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

Tenga en cuenta las comillas simples alrededor de la etiqueta de la plantilla.

Aunque mi próxima pregunta sería: ¿es REALMENTE seguro?

Actualizar

Una versión actualizada que funciona en django 1.8 de la etiqueta de plantilla anterior que también maneja pasar una lista de valores plana, es decir. 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) 

Nuevo en Django 2.1: json_script

Django 2.1 introdujo una nueva etiqueta de plantilla: json_script . Es casi exactamente lo que está buscando, podría ser incluso mejor. Convierte un valor de Python en JSON, envuelto en una etiqueta . Así que esta plantilla:

 {{ value|json_script:"foobar" }} 

... produciría esto:

  

Esta no es una etiqueta normal de Javascript , no se ejecuta, es solo JSON. Si desea acceder a los contenidos en su Javascript, puede hacerlo así:

 var value = JSON.parse(document.getElementById('foobar').textContent); 

Esta etiqueta se ha codificado para que se escape correctamente, por ejemplo, una cadena con no rompa nada.

Mira esta respuesta también.

Pero no es una manera de carga alta. Debes:

a) Crear archivos JSON, colocarlos en disco o S3. En caso de que JSON sea estático.

b) Si JSON es dynamic. Genere JSON en la url por separado (como API) en su aplicación.

Y, carga por JS directamente en cualquier caso. Por ejemplo:

$.ajax('/get_json_file.json')

PD: Perdón por mi inglés.