307

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

4

12 回答 12

303

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

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

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

请记住两件事:

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

虽然对于第一个问题我们无能为力,除了警告人们,我们确实需要解决第二个问题。

于 2012-06-19T19:55:54.040 回答
126

您可以尝试逐字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 %}

于 2012-05-30T08:30:07.620 回答
43

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

在神社2

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

在 Django 模板中(1.5 以上)

{% verbatim %}    
    // here you can write angularjs template tags.
{% endverbatim %}
于 2013-05-31T02:39:33.923 回答
31

我们在 Django 'ng' 中创建了一个非常简单的过滤器,可以轻松混合两者:

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)
于 2012-08-24T01:01:31.210 回答
27

所以我今天在 Angular IRC 频道中得到了一些很大的帮助。事实证明,您可以非常轻松地更改 Angular 的模板标签。下面的必要片段应包含在您的角度包含之后(给定的示例出现在他们的邮件列表中,并将(())用作新的模板标签,替代您自己的):

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属性,可以设置为您想要的任何标签。

于 2011-12-10T01:51:43.403 回答
18

我投票反对使用双括号 (()) 作为模板标签。只要不涉及函数调用,它就可以很好地工作,但是当尝试以下

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

在 Mac 上使用 Firefox (10.0.2) 我得到了一个非常长的错误,而不是预期的逻辑。<[]> 对我来说很顺利,至少到目前为止。

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

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

API 文档

于 2012-03-07T20:26:27.283 回答
16

我发现下面的代码很有帮助。我在这里找到了代码: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)
于 2012-11-11T12:34:54.957 回答
16

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

<span ng-bind="name"></span>
于 2014-02-27T14:45:50.850 回答
12

如果您使用 django 1.5 和更新版本,请使用:

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

如果您在 appengine 上被 django 1.2 卡住,请使用这样的逐字模板命令扩展 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

于 2013-02-04T14:16:00.157 回答
7

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

例如, using{% templatetag openvariable %}将输出{{.

于 2011-11-29T02:26:58.523 回答
3

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

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

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

于 2013-06-29T20:42:15.613 回答
0

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

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

其他任何东西都是 XSS 向量。

这是因为用户可以将任何未被 Django 转义的 Angular 分隔符输入到插值字符串中;如果有人将他们的用户名设置为“{{evil_code}}”,Angular 会很高兴地运行它。但是,如果您使用Django escapes 以外的字符,则不会发生这种情况。

于 2016-02-21T17:49:40.420 回答