AngularJS与Django - 冲突的模板标签

时间:2011-11-28 21:55:49

标签: javascript django django-templates angularjs

我想将AngularJS与Django一起使用,但是他们都使用{{ }}作为模板标签。是否有一种简单的方法可以更改其中一个以使用其他自定义模板标记?

13 个答案:

答案 0 :(得分:296)

对于Angular 1.0,您应该使用$ interpolateProvider apis配置插值符号:http://docs.angularjs.org/api/ng.$interpolateProvider

这样的事情可以解决问题:

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

请记住两件事:

  • 混合服务器端和客户端模板很少是一个好主意,应谨慎使用。主要问题是:可维护性(难以阅读)和安全性(双重插值可能会暴露出新的安全性向量 - 例如,当逃避服务器端和客户端模板本身可能是安全的时,它们的组合可能不是)。
  • 如果您开始使用在其模板中使用{{ }}的第三方指令(组件),那么您的配置将会破坏它们。 (fix pending

虽然我们无法对第一个问题采取任何措施,但警告人员除外,我们确实需要解决第二个问题。

答案 1 :(得分:118)

你可以试试verbatim Django模板标签 并像这样使用它:

<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 %}

答案 2 :(得分:42)

如果你正确地分开了页面部分,那么你可以在“原始”标签范围内轻松使用angularjs标签。

在jinja2中

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

在Django模板中(1.5以上)

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

答案 3 :(得分:29)

我们在Django'ng'中创建了一个 very 简单过滤器,可以很容易地将两者混合使用:

foo.html:

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

ng过滤器如下所示:

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)

答案 4 :(得分:26)

所以我今天在Angular IRC频道得到了很多帮助。事实证明,您可以非常轻松地更改Angular的模板标签。在您的角度包含后,应包含以下必要的摘要(给定的示例显示在mailing lists上,并使用(())作为新模板标记,替换为您自己的代码:

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

此外,我还指出了即将推出的增强功能,它将公开startSymbolendSymbol属性,这些属性可以设置为您想要的任何标记。

答案 5 :(得分:17)

我投票反对使用双括号(())作为模板标记。只要不涉及函数调用但是在尝试以下

时,它可能会很好地工作
ng:disabled=(($invalidWidgets.visible()))
在Mac上使用Firefox(10.0.2)

我得到了一个非常长的错误而不是预期的逻辑。百分比抑制率]&GT;对我来说很顺利,至少到现在为止。

修改2012-03-29: 请注意,不推荐使用$ invalidWidgets。但是我仍然使用另一个包装而不是双括号。对于任何高于0.10.7的角度版本(我猜),您可以在应用程序/模块定义中更轻松地更改包装:

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

API docs

答案 6 :(得分:15)

我发现以下代码很有帮助。我在这里找到了代码: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)

答案 7 :(得分:14)

您始终可以使用ng-bind而不是{{}} http://docs.angularjs.org/api/ng/directive/ngBind

<span ng-bind="name"></span>

答案 8 :(得分:11)

如果你使用django 1.5和更新的使用:

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

如果你坚持使用django 1.2 on appengine,请使用verbatim模板命令扩展django语法,如下所示...

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

在您的文件中使用:

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

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

答案 9 :(得分:9)

对于AngularJS v1.3.3,您应该像这样定义自己的模板标签

AngularJS模块

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

<强>网页

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

答案 10 :(得分:7)

您可以使用{% templatetag %}标记告诉Django输出{{}}以及其他保留的模板字符串。

例如,使用{% templatetag openvariable %}会输出{{

答案 11 :(得分:3)

我会坚持使用django标签{{}}以及angularjs {{}}的解决方案,其中包含逐字节或模板标签。

这只是因为您可以通过$ interpolateProvider.startSymbol $ interpolateProvider.endSymbol更改angularjs的工作方式(如上所述)但是如果您开始使用其他angularjs组件(如ui-bootstrap),您会发现一些模板已经使用标准angularjs标记{{}}构建了ALREADY。

例如,请查看https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html

答案 12 :(得分:0)

如果您进行任何服务器端插值,唯一正确的方法是使用<>

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

其他任何东西都是XSS载体。

这是因为任何未被Django转义的角度分隔符都可以由用户输入到插值字符串中;如果有人将其用户名设置为“{{evil_code}}”,Angular will happily run it。但是,如果您使用character than Django escapes,则不会发生这种情况。