2008-11-18 46 views
132

Cuando renderizo una página usando el renderizador de plantilla Django, puedo pasar una variable de diccionario que contiene varios valores para manipularlos en la página usando {{ myVar }}.Variables de plantilla Django y Javascript

¿Hay alguna manera de acceder a la misma variable en Javascript (quizás usando el DOM, no sé cómo Django hace que las variables sean accesibles)? Quiero poder buscar detalles utilizando una búsqueda AJAX basada en los valores contenidos en las variables pasadas.

Respuesta

200

El {{variable}} se sustituye directamente en el HTML. Hacer una fuente de vista; no es una "variable" ni nada por el estilo. Es solo texto renderizado.

Habiendo dicho eso, puede poner este tipo de sustitución en su JavaScript.

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

Esto le da javascript "dinámico".

+17

Tenga en cuenta que de acuerdo con [esta solución] (http://stackoverflow.com/questions/298772/django-template-variables-and-javascript/1187881#1187881), esto es vulnerable a los ataques de inyección – Casebash

+12

@Casebash: Para tales ocasiones, existe el filtro 'escapejs':' escapejs ('<>') -> u '\\ u003C \\ u003E'' –

+18

Solo para agregar a esto como referencia: si el "algúnDjangoVariable" resulta ser JSON , asegúrese de usar {{someDjangoVariable | safe}} para eliminar " – Mark

7

Para un diccionario, primero es mejor que codifique a JSON. Puede usar simplejson.dumps() o si desea convertir desde un modelo de datos en App Engine, puede usar encode() desde la biblioteca GQLEncoder.

+2

Este enfoque funcionó después de desactivar el autoescape django. –

+0

Nota ese 'simplejson' se convirtió en 'json' a partir de django 1.7, creo. – fiveclubs

34

Una solución que funcionó para mí está utilizando el campo de entrada oculto en la plantilla

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

a continuación, obtener el valor en javascript esta manera,

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

tenga cuidado, dependiendo de cómo use la variable/forma, el usuario podría poner lo que quiera. – AndyL

+1

es posible que también desee establecer su campo de entrada para leer solo (consulte este enlace http://www.w3schools.com/tags/att_input_readonly.asp) –

+0

Si es algo que no alterará una base de datos o no se enviará a una consulta de base de datos, estaría bien. @AndyL – James111

5

Cuando la variable es devuelto por Django se convierte todas las cotizaciones en &quot;. El uso de {{someDjangoVariable|safe}} provoca un error de Javascript.

Para solucionar este uso Javascript .replace:

<script type="text/javascript"> 
    var json = "{{someDjangoVariable}}".replace(/&quot;/g,"\"") 
</script> 
+0

Nunca pensé en eso ... ¡gran idea! – domachine

+1

Utilice ['escapejs'] (https://docs.djangoproject.com/en/dev/ref/templates/builtins/#escapejs) filtro de plantilla en lugar de' .replace (..) ' – Medorator

38

PRECAUCIÓN Comprobar#17419 billete para la discusión sobre la adición de etiquetas similar en Django núcleo y posibles vulnerabilidades XSS introducidas mediante el uso de esta etiqueta plantilla con los datos generados por el usuario. Comment de amacneil discute la mayoría de las preocupaciones planteadas en el boleto.


Creo que la forma más flexible y práctico de hacer esto es definir un filtro de plantilla para las variables que desee utilizar en el código JS. Esto le permite asegurarse de que sus datos se hayan escapado correctamente y que pueda usarlos con estructuras de datos complejas, como dict y list. Es por eso que escribo esta respuesta a pesar de que hay una respuesta aceptada con muchos votos ascendentes.

Aquí es un ejemplo de filtro de plantilla:

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

estos Filtros plantilla convierte variable para cadena JSON. Se puede utilizar de este modo:

// myapp/templates/example.html 

{% load js %} 

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

Eso es bueno porque permite copiando solo algunas variables de entrada de plantilla de Django a Javascript y el código del lado del servidor no necesita saber qué estructuras de datos debe usar Javascript y por lo tanto convertir a JSON antes de representar la plantilla de Django. Use esto o siempre copie todas las variables de Django a Javascript. –

+0

Pero tenga en cuenta: http://stackoverflow.com/questions/23752156/are-all-json-objects-also-valid-javascript-objects –

+0

Nice. ¿Es eso lo mismo que simplemente usar https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#safe? –

5

Esto es lo que estoy haciendo con mucha facilidad: he modificado mi base.archivo html para mi plantilla y poner que en el fondo:

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

entonces cuando quiero utilizar una variable en los archivos javascript, puedo crear un diccionario DJdata y lo añado al contexto de un JSON: context['DJdata'] = json.dumps(DJdata)

Espero que ayude!

+2

Esto es increíble, gracias! – mAvbig

3

Estaba enfrentando un problema similar y la respuesta sugerida por S.Lott funcionó para mí.

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

Sin embargo, me gustaría señalar principal limitación aplicación aquí. Si planea colocar su código de JavaScript en un archivo diferente e incluir ese archivo en su plantilla. Esto no funcionará

Esto funciona solo cuando la plantilla principal y el código de JavaScript están en el mismo archivo. Probablemente el equipo de django pueda abordar esta limitación.

+1

¿Cómo podemos superar esto? –

+0

Para solucionar esto, puede colocar variables globales de Javascript como el ejemplo que se muestra justo antes de incluir el archivo Javascript estático. Su archivo Javascript estático tendrá acceso a todas las variables globales de esa manera. – Bobort

0

Para un objeto JavaScript almacenado en un campo de Django como texto, que debe convertirse de nuevo en un objeto JavaScript inserta de forma dinámica en la escritura de páginas, es necesario utilizar tanto escapejs y JSON.parse():

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

de escapejs Django maneja las comillas correctamente, y JSON.parse() convierte la cadena nuevamente en un objeto JS.

Cuestiones relacionadas