javascript django django-templates angularjs

javascript - django+angular



AngularJS con Django-Etiquetas de plantillas en conflicto (13)

Quiero usar AngularJS con Django, pero ambos usan {{ }} como etiquetas de plantilla. ¿Existe una manera fácil de cambiar uno de los dos para usar alguna otra etiqueta de plantilla personalizada?


Así que hoy recibí una gran ayuda en el canal Angular IRC. Resulta que puedes cambiar las etiquetas de plantillas de Angular muy fácilmente. Los fragmentos necesarios a continuación deben incluirse después de su inclusión angular (el ejemplo dado aparece en sus listas de correo y usaría (()) como las nuevas etiquetas de la plantilla, sustituyendo las suyas propias):

angular.markup(''(())'', function(text, textNode, parentElement){ if (parentElement[0].nodeName.toLowerCase() == ''script'') return; text = text.replace(//(/(/g,''{{'').replace(//)/)/g, ''}}''); textNode.text(text); return angular.markup(''{{}}'').call(this, text, textNode, parentElement); }); angular.attrMarkup(''(())'', function(value, name, element){ value = value.replace(//(/(/g,''{{'').replace(//)/)/, ''}}''); element[0].setAttribute(name, value); return angular.attrMarkup(''{{}}'').call(this, value, name, element); });

Además, se me indicó una próxima mejora que expondrá las propiedades startSymbol y endSymbol que se pueden establecer en las etiquetas que desee.


Creamos un filtro muy simple en Django ''ng'' que facilita la mezcla de los dos:

foo.html:

... <div> {{ django_context_var }} {{ ''angularScopeVar'' | ng }} {{ ''angularScopeFunction()'' | ng }} </div> ...

El filtro ng ve así:

from django import template from django.utils import safestring register = template.Library() @register.filter(name=''ng'') def Angularify(value): return safestring.mark_safe(''{{%s}}'' % value)


Encontré útil el siguiente código. Encontré el código aquí: http://djangosnippets.org/snippets/2787/

""" filename: angularjs.py Usage: {% ng Some.angular.scope.content %} e.g. {% load angularjs %} <div ng-init="yourName = ''foobar''"> <p>{% ng yourName %}</p> </div> """ from django import template register = template.Library() class AngularJS(template.Node): def __init__(self, bits): self.ng = bits def render(self, ctx): return "{{%s}}" % " ".join(self.ng[1:]) def do_angular(parser, token): bits = token.split_contents() return AngularJS(bits) register.tag(''ng'', do_angular)


Me quedaría con una solución que usa tanto etiquetas django {{}} como angularjs {{}} con una sección textual o una plantilla de plantilla.

Esto se debe simplemente a que puede cambiar la forma en que funciona angularjs (como se mencionó) a través de $ interpolateProvider.startSymbol $ interpolateProvider.endSymbol, pero si comienza a usar otros componentes de angularjs como el ui-bootstrap, verá que algunas de las plantillas ESTÁN CONSTRUIDAS. con etiquetas estándar angularjs {{}}.

Por ejemplo, consulte https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html .


Para Angular 1.0, debe usar $ interpolateProvider apis para configurar los símbolos de interpolación: http://docs.angularjs.org/api/ng.$interpolateProvider .

Algo como esto debería hacer el truco:

myModule.config(function($interpolateProvider) { $interpolateProvider.startSymbol(''{[{''); $interpolateProvider.endSymbol(''}]}''); });

Tenga en cuenta dos cosas:

  • mezclar plantillas del lado del servidor y del lado del cliente rara vez es una buena idea y debe usarse con precaución. Los problemas principales son: la capacidad de mantenimiento (difícil de leer) y la seguridad (la doble interpolación podría exponer un nuevo vector de seguridad, por ejemplo, mientras que el escape del servidor y la plantilla del lado del cliente por sí mismos puede ser seguro, su combinación podría no serlo).
  • Si comienza a usar directivas (componentes) de terceros que usan {{ }} en sus plantillas, su configuración las romperá. ( arreglo pendiente )

Si bien no hay nada que podamos hacer con respecto al primer problema, excepto para advertir a las personas, necesitamos abordar el segundo problema.


Para AngularJS v1.3.3 debe definir sus propias etiquetas de plantilla como esta

Módulo angular js

angular.module(''myapp'', []).config(function($interpolateProvider) { $interpolateProvider.startSymbol(''{$''); $interpolateProvider.endSymbol(''$}''); });

Página web

<a>{$ variable $}</a>


Puede decirle a Django que genere {{ y }} , así como otras cadenas de plantillas reservadas usando la etiqueta {% templatetag %} .

Por ejemplo, usar {% templatetag openvariable %} generaría {{ .


Si realiza una interpolación del lado del servidor, la única forma correcta de hacerlo es con <>

$interpolateProvider.startSymbol(''<{'').endSymbol(''}>'');

Cualquier otra cosa es un vector XSS.

Esto se debe a que el usuario puede ingresar en la cadena interpolada cualquier delimitador angular que Django no haya escapado a Django; si alguien establece su nombre de usuario como "{{evil_code}}", Angular lo ejecutará con mucho gusto. Sin embargo, si usas un personaje del que Django escapa , esto no sucederá.


Si separó correctamente las secciones de la página, puede usar fácilmente las etiquetas angularjs en el ámbito de la etiqueta "sin procesar".

En jinja2

{% raw %} // here you can write angularjs template tags. {% endraw %}

En la plantilla de Django (por encima de 1.5)

{% verbatim %} // here you can write angularjs template tags. {% endverbatim %}


Si usas django 1.5 y más reciente:

{% verbatim %} {{if dying}}Still alive.{{/if}} {% endverbatim %}

Si está atascado con django 1.2 en appengine, extienda la sintaxis de django con el comando de plantilla textual como este ...

from django import template register = template.Library() class VerbatimNode(template.Node): def __init__(self, text): self.text = text def render(self, context): return self.text @register.tag def verbatim(parser, token): text = [] while 1: token = parser.tokens.pop(0) if token.contents == ''endverbatim'': break if token.token_type == template.TOKEN_VAR: text.append(''{{'') elif token.token_type == template.TOKEN_BLOCK: text.append(''{%'') text.append(token.contents) if token.token_type == template.TOKEN_VAR: text.append(''}}'') elif token.token_type == template.TOKEN_BLOCK: text.append(''%}'') return VerbatimNode(''''.join(text))

En su archivo de uso:

from google.appengine.ext.webapp import template template.register_template_library(''utilities.verbatim_template_tag'')

Fuente: http://bamboobig.blogspot.co.at/2011/09/notebook-using-jquery-templates-in.html



Tal vez puedas probar la etiqueta de plantilla de Django verbatim y usarla así:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> {% verbatim %} <div ng-app=""> <p>10 is {{ 5 + 5 }}</p> </div> {% endverbatim %}


Voto en contra usando doble paréntesis (()) como etiqueta de plantilla. Puede funcionar bien siempre que no se trate de una llamada de función, pero cuando se intente lo siguiente

ng:disabled=(($invalidWidgets.visible()))

con Firefox (10.0.2) en Mac recibí un error terriblemente largo en lugar de la lógica deseada. <[]> me fue bien, al menos hasta ahora.

Editar 2012-03-29: Tenga en cuenta que $ invalidWidgets está en desuso. Sin embargo, todavía usaría otra envoltura que dobleces dobles. Para cualquier versión angular superior a 0.10.7 (supongo) podría cambiar la envoltura mucho más fácil en la definición de su aplicación / módulo:

angular.module(''YourAppName'', [], function ($interpolateProvider) { $interpolateProvider.startSymbol(''<[''); $interpolateProvider.endSymbol('']>''); });

Documentos API .