AngularJS 与 Django - 冲突的模板标签

IT技术 javascript django django-templates angularjs
2021-01-30 17:59:26

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

6个回答

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

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

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

请记住两件事:

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

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

有什么方法也可以更新原始输出的 $interpolateProvider 吗?例如 {{{foo}}} 变成 {{[{foo}]}} ?
2021-03-11 17:59:26
由于 $interpolateProvider 在用作 setter 时会返回 self,因此这里有一个稍微紧凑的版本: $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
2021-03-12 17:59:26
@btlachance - 我扩展了答案。
2021-03-28 17:59:26
您介意解释一下您的第一点(维护、安全以及混合服务器端和客户端模板的其他问题)吗?多一点解释会有所帮助。
2021-03-31 17:59:26
看起来“修复”已关闭。这是否意味着现在使用第三方组件不安全?
2021-04-08 17:59:26

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

虽然这是一个非常有效的解决方案,但在某些情况下,我希望能够使用来自服务器的数据引导我的视图,因此这会很快变得混乱。想想用户的用户名之类的东西,它不会改变,所以我只是将它写入服务器的模板中,但可能会有一些我会用 angular 写入的部分。
2021-03-15 17:59:26
要从 Django 上下文中获取值到 javascript 中,您应该使用json_script内置的模板标记。这将创建一个<script />具有给定 ID标签,然后您可以将其加载到您的 javascript 中,而无需注入向量。
2021-03-20 17:59:26
有办法从设置中更改 Django 默认括号会很好,但这也有效。
2021-03-29 17:59:26
从 1.5 版开始,逐字逐字成为 Django 核心标签的一部分:docs.djangoproject.com/en/dev/ref/templates/builtins/...
2021-04-05 17:59:26
在 Django 1.7 中你不需要逐字加载,因为它在标准标签库中。您只需要使用标签本身。
2021-04-06 17:59:26

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

在 jinja2

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

在 Django 模板中(1.5 以上)

{% verbatim %}    
    // here you can write angularjs template tags.
{% endverbatim %}
这个解决方案不会破坏兼容性,因为外部包是公认的答案。
2021-04-05 17:59:26

我们在 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)
你如何创建 ng 过滤器?你能添加一个例子吗?
2021-03-12 17:59:26
另一种非常有效的方法,但是我宁愿在一个地方更改标签而不是在许多地方添加过滤器......
2021-04-03 17:59:26
@WesAlvaro 不幸的是,我只能接受一个答案。
2021-04-04 17:59:26
更新了答案。@Endophage我有很多更有棱角{{}}对,比我的Django {{}}对,所以我宁愿更新Django的人。
2021-04-06 17:59:26

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

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

另外,我指着即将到来的增强,将暴露startSymbol,并endSymbol可以设置为任何的属性标签,你的愿望。

这就是你在 angularjs 1.0 中的做法:var m = angular.module('myApp', []); m.config(function($interpolateProvider) { $interpolateProvider.startSymbol('(('); $interpolateProvider.endSymbol('))'); });
2021-04-04 17:59:26
角度 IRC 通道。不管是谁,我在#angularjs 找到了一个
2021-04-04 17:59:26