Angularjs con django - etiquetas de plantilla conflictivas
-
25-10-2019 - |
Pregunta
Quiero usar angularjs con django, sin embargo, ambos usan {{ }}
Como sus etiquetas de plantilla. ¿Hay una manera fácil de cambiar uno de los dos para usar alguna otra etiqueta de plantilla personalizada?
Solución
Para Angular 1.0 debe usar las API $ InterpolateProvider 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 principales problemas son: mantenibilidad (difícil de leer) y seguridad (la doble interpolación podría exponer un nuevo vector de seguridad, por ejemplo, mientras se puede escapar de la plantilla de servidor y clientes por sí mismos, su combinación podría no ser).
- Si comienza a usar directivas (componentes) de terceros que usan
{{ }}
En sus plantillas, su configuración las romperá. (Arreglar pendiente)
Si bien no hay nada que podamos hacer sobre el primer problema, excepto para advertir a las personas, debemos abordar el segundo problema.
Otros consejos
tal vez puedas intentar literal Etiqueta de plantilla de Django y úsela 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 %}
Si hizo secciones separadas de la página correctamente, puede usar fácilmente etiquetas AngularJS en el alcance de la etiqueta "en bruto".
En jinja2
{% raw %}
// here you can write angularjs template tags.
{% endraw %}
En plantilla de Django (por encima de 1.5)
{% verbatim %}
// here you can write angularjs template tags.
{% endverbatim %}
Creamos un muy Filtro simple en django 'ng' que facilita la mezcla de los dos:
foo.html:
...
<div>
{{ django_context_var }}
{{ 'angularScopeVar' | ng }}
{{ 'angularScopeFunction()' | ng }}
</div>
...
los ng
El filtro se 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)
Así que hoy obtuve una gran ayuda en el canal Angular IRC. Resulta que puede cambiar las etiquetas de plantilla 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 su listas de correo y usaría (())
Como la nueva plantilla etiqueta, sustituya la suya):
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, me señalaron una próxima mejora que expondrá startSymbol
y endSymbol
Propiedades que se pueden configurar en las etiquetas que desee.
Voto en contra de usar paréntesis dobles (()) como etiqueta de plantilla. Puede funcionar bien siempre que no se involucre ninguna llamada de función, pero cuando se prueba lo siguiente
ng:disabled=(($invalidWidgets.visible()))
Con Firefox (10.0.2) en Mac obtuve un error terriblemente largo en lugar de la lógica prevista. <[]> 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 otro envoltorio que los tirantes dobles. Para cualquier versión angular superior a 0.10.7 (supongo), puede cambiar el envoltorio mucho más fácil en la definición de su aplicación / módulo:
angular.module('YourAppName', [], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<[');
$interpolateProvider.endSymbol(']>');
});
Encontré el código a continuación útil. 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)
Siempre puedes usar NG-Bind en lugar de {{}}http://docs.angularjs.org/api/ng/directive/ngbind
<span ng-bind="name"></span>
Si usa Django 1.5 y un uso más nuevo:
{% 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 literal 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 archivo:
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
Puedes decirle a Django que salga {{
y }}
, así como otras cadenas de plantilla reservadas usando el {% templatetag %}
etiqueta.
Por ejemplo, usando {% templatetag openvariable %}
saldría {{
.
Me quedaría con una solución que use ambas etiquetas Django {{}} también angularjs {{}} con una sección literal o templateTag.
Eso es simplemente porque 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 AngularJS como el UI-Bootstrap, encontrará que algunas de las plantillas ya están construidas con etiquetas AngularJS estándar {{}}.
Por ejemplo, mira https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html.
Si hace alguna interpolación del lado del servidor, el solamente La forma correcta de hacer esto es con <>
$interpolateProvider.startSymbol('<{').endSymbol('}>');
Cualquier otra cosa es un vector XSS.
Esto se debe a que el usuario puede ingresar a los delimitadores angulares que el usuario no escape por Django en la cadena interpolada; Si alguien establece su nombre de usuario como "{{Evil_code}}", Angular felizmente lo ejecutará. Si usa un carácter que el django escapa, sin embargo, esto no sucederá.