AngularJS com Django – tags de template conflitantes

Eu quero usar o AngularJS com o Django, mas ambos usam {{ }} como suas tags de template. Existe uma maneira fácil de alterar um dos dois para usar outra tag de modelo personalizada?

Para o Angular 1.0, você deve usar o $ interpolateProvider apis para configurar os símbolos de interpolação: http://docs.angularjs.org/api/ng.$interpolateProvider .

Algo como isso deve fazer o truque:

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

Tenha em mente duas coisas:

  • A mistura de modelos do lado do servidor e do lado do cliente raramente é uma boa ideia e deve ser usada com cuidado. Os principais problemas são: capacidade de manutenção (difícil de ler) e segurança (a interpolação dupla pode expor um novo vetor de segurança – por exemplo, embora a fuga de modelos do lado do servidor e do cliente seja segura, sua combinação pode não ser).
  • Se você começar a usar diretivas de terceiros (componentes) que usam {{ }} em seus modelos, sua configuração as quebrará. ( correção pendente )

Embora não haja nada que possamos fazer sobre a primeira questão, exceto para alertar as pessoas, precisamos abordar a segunda questão.

você pode, talvez, tentar verbatim tag template Django e usá-lo assim:

  {% verbatim %} 

10 is {{ 5 + 5 }}

{% endverbatim %}

Se você separou seções da página corretamente, poderá usar facilmente as tags angularjs no escopo da tag “bruta”.

Em jinja2

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

No modelo do Django (acima de 1.5)

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

Nós criamos um filtro muito simples no Django ‘ng’ que facilita mixar os dois:

foo.html:

 ... 
{{ django_context_var }} {{ 'angularScopeVar' | ng }} {{ 'angularScopeFunction()' | ng }}
...

O filtro ng é assim:

 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) 

Então eu tenho uma grande ajuda no canal de IRC Angular hoje. Acontece que você pode alterar as tags de template do Angular com muita facilidade. Os trechos necessários abaixo devem ser incluídos após sua inclusão angular (o exemplo fornecido aparece em suas listas de discussão e usaria (()) como as novas tags de modelo, substituindo as suas próprias):

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

Além disso, fui apontado para um aprimoramento futuro que exporá as propriedades endSymbol e endSymbol que podem ser definidas para qualquer tag desejada.

Eu voto contra o uso de parênteses duplos (()) como tag de template. Pode funcionar bem, desde que nenhuma chamada de function esteja envolvida, mas quando experimentada a seguinte

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

com o Firefox (10.0.2) no Mac eu tenho um erro muito longo em vez da lógica pretendida. <[]> correu bem para mim, pelo menos até agora.

Edit 2012-03-29: Por favor, note que $ invalidWidgets é obsoleto. No entanto, eu ainda usaria outro invólucro do que chaves duplas. Para qualquer versão angular maior que 0.10.7 (eu acho), você poderia alterar o wrapper muito mais facilmente em sua definição de aplicativo / módulo:

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

Documentos de API .

Eu achei o código abaixo útil. Eu encontrei o código aqui: http://djangosnippets.org/snippets/2787/

 """ filename: angularjs.py Usage: {% ng Some.angular.scope.content %} eg {% load angularjs %} 

{% ng yourName %}

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

Você sempre pode usar ng-bind em vez de {{}} http://docs.angularjs.org/api/ng/directive/ngBind

  

Se você usa o django 1.5 e o uso mais recente:

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

Se você está preso com o django 1.2 no appengine, estenda a syntax do django com o comando verbatim template 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)) 

Em seu arquivo use:

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

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

Para o AngularJS v1.3.3 você deve definir suas próprias tags de template como esta

Módulo AngularJS

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

Página da web

 {$ variable $} 

Você pode dizer ao Django para produzir {{ e }} , bem como outras strings de template reservadas usando a tag {% templatetag %} .

Por exemplo, usar {% templatetag openvariable %} produziria {{ .

Eu ficaria com uma solução que usa tanto as tags do django {{}} quanto o angularjs {{}} com uma seção ou template textual.

Isso é simplesmente porque você pode mudar a maneira como o angularjs funciona (como mencionado) através do $ interpolateProvider.startSymbol $ interpolateProvider.endSymbol, mas se você começar a usar outros componentes angularjs como o ui-bootstrap você verá que alguns dos templates já estão construídos com tags angularjs padrão {{}}.

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

Se você fizer qualquer interpolação do lado do servidor, a única maneira correta de fazer isso é com <>

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

Qualquer outra coisa é um vetor XSS.

Isso ocorre porque quaisquer delimitadores angulares que não são escapados pelo Django podem ser inseridos pelo usuário na string interpolada; se alguém definir seu nome de usuário como “{{evil_code}}”, o Angular ficará feliz em executá-lo . Se você usar um personagem que o Django escapa , no entanto, isso não acontecerá.