AngularJS с Django - конфликтующие теги шаблонов
Я хочу использовать AngularJS с Django, однако они оба используют {{ }}
как их шаблоны тегов. Есть ли простой способ изменить один из двух, чтобы использовать какой-либо другой пользовательский шаблонный тег?
13 ответов
Для Angular 1.0 вы должны использовать apis $interpolateProvider для настройки символов интерполяции: http://docs.angularjs.org/api/ng.%24interpolateProvider.
Нечто подобное должно сработать:
myModule.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
Имейте в виду две вещи:
- Смешивание шаблонов на стороне сервера и на стороне клиента редко является хорошей идеей и должно использоваться с осторожностью. Основные проблемы: удобство сопровождения (трудно читаемое) и безопасность (двойная интерполяция может обнажить новый вектор безопасности - например, если экранирование серверной части и клиентской стороны само по себе может быть безопасным, их комбинация может и не быть).
- если вы начнете использовать сторонние директивы (компоненты), которые используют
{{ }}
в их шаблонах, тогда ваша конфигурация сломает их. ( исправление ожидается)
Хотя с первым вопросом мы ничего не можем поделать, кроме как предупреждать людей, нам нужно решить второй вопрос.
Вы можете, возможно, попробовать дословный тег шаблона 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 %}
Если вы правильно сделали отдельные разделы страницы, то вы можете легко использовать теги angularjs в области "необработанных" тегов.
В jinja2
{% raw %}
// here you can write angularjs template tags.
{% endraw %}
В шаблоне Django (выше 1.5)
{% verbatim %}
// here you can write angularjs template tags.
{% endverbatim %}
Мы создали очень простой фильтр в 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)
Так что сегодня я получил большую помощь на канале 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);
});
Кроме того, мне было указано на предстоящее улучшение, которое разоблачит startSymbol
а также endSymbol
свойства, которые могут быть установлены на любые теги, которые вы хотите.
Я голосую против использования двойных скобок (()) в качестве тега шаблона. Это может работать хорошо до тех пор, пока не задействован вызов функции, но при попытке выполнить следующее
ng:disabled=(($invalidWidgets.visible()))
с Firefox (10.0.2) на Mac я получил ужасно длинную ошибку вместо предполагаемой логики. <[]> хорошо для меня, по крайней мере, до сих пор.
Изменить 2012-03-29: Обратите внимание, что $invalidWidgets устарела. Однако я бы по-прежнему использовал другую обертку, чем двойные скобки. Для любой угловой версии выше 0.10.7 (я полагаю) вы могли бы изменить оболочку намного проще в определении вашего приложения / модуля:
angular.module('YourAppName', [], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<[');
$interpolateProvider.endSymbol(']>');
});
Вы всегда можете использовать ng-bind вместо {{}} http://docs.angularjs.org/api/ng/directive/ngBind
<span ng-bind="name"></span>
Я нашел код ниже полезным. Я нашел код здесь: 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)
Если вы используете django 1.5 и новее, используйте:
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
Если вы застряли с django 1.2 в appengine, расширьте синтаксис django с помощью команды шаблонов verbatim, как это...
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
Для AngularJS v1.3.3 вы должны определить свои собственные шаблоны тегов, как это
Модуль AngularJS
angular.module('myapp', []).config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');
});
Страница интернета
<a>{$ variable $}</a>
Вы можете сказать Django для вывода {{
а также }}
, а также другие зарезервированные строки шаблона с помощью {% templatetag %}
тег.
Например, используя {% templatetag openvariable %}
будет выводить {{
,
Я бы остановился на решении, которое использует оба тега django {{}}, а также angularjs {{}} с дословным разделом или тегом шаблона.
Это просто потому, что вы можете изменить способ работы angularjs (как уже упоминалось) через $interpolateProvider.startSymbol $interpolateProvider.endSymbol, но если вы начнете использовать другие компоненты angularjs, такие как ui-bootstrap, вы обнаружите, что некоторые шаблоны уже построены со стандартными тегами angularjs {{}}.
Например, посмотрите на https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html.
Если вы делаете какую-либо серверную интерполяцию, единственный правильный способ сделать это с <>
$interpolateProvider.startSymbol('<{').endSymbol('}>');
Все остальное является вектором XSS.
Это связано с тем, что любые угловые разделители, которые не экранированы Django, могут быть введены пользователем в интерполированную строку; если кто-то установит свое имя пользователя как "{{evil_code}}", Angular с удовольствием его запустит. Если вы используете персонажа, то Django убегает, однако этого не произойдет.