AngularJS с Django - конфликтующие теги шаблонов

281

Я хочу использовать AngularJS с Django, но оба они используют {{ }} в качестве тегов шаблонов. Есть ли простой способ изменить один из двух, чтобы использовать другой пользовательский шаблонный тег?

  • 1
    Я только вынести один шаблон из Джанго templates каталога, остальное я ставлю в static . Таким образом, у вас нет помех. Вот учебник, который я написал здесь: coderwall.com/p/bzjuka/…
  • 0
    как передать данные между angular2 и jinja2? Любая помощь
Показать ещё 1 комментарий
Теги:
django-templates

13 ответов

275
Лучший ответ

Для Angular 1.0 вы должны использовать api-интерполяциюProvider для настройки символов интерполяции: http://docs.angularjs.org/api/ng.$interpolateProvider.

Что-то вроде этого должно сделать трюк:

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

Помните о двух вещах:

  • Смешивание серверных и клиентских шаблонов редко является хорошей идеей и должно использоваться с осторожностью. Основные проблемы: ремонтопригодность (трудно читаемая) и безопасность (двойная интерполяция может выставить новый вектор безопасности - например, хотя экранирование серверов и клиентских шаблонов сами по себе могут быть безопасными, их комбинация может и не быть).
  • если вы начнете использовать сторонние директивы (компоненты), которые используют {{ }} в своих шаблонах, тогда ваша конфигурация сломает их. (исправить ошибку)

Пока мы ничего не можем сделать по первому вопросу, кроме предупреждения людей, нам нужно решить вторую проблему.

  • 0
    Шаблоны начальной загрузки с данными - не редкость. Это на самом деле рекомендуется в backbone.js
  • 4
    Не могли бы вы объяснить свой первый пункт (обслуживание, безопасность и другие вопросы по смешиванию шаблонов на стороне сервера и на стороне клиента)? Немного больше объяснений было бы полезно.
Показать ещё 11 комментариев
107

вы можете попробовать verbatim Шаблон тега Django и используйте его следующим образом:

<script src="/angular.min.js"></script>

{% verbatim %}
<div ng-app="">
    <p>10 is {{ 5 + 5 }}</p>
</div>
{% endverbatim %}
  • 0
    Хотя это очень правильное решение, в некоторых случаях я хочу иметь возможность загружать свои представления с данных с сервера, чтобы это быстро запуталось. Подумайте, например, как имя пользователя, оно не изменится, поэтому я просто запишу его в шаблон на сервере, но могут быть фрагменты, которые я напишу с помощью angular.
  • 16
    Verbatim является частью основных тегов Django начиная с версии 1.5: docs.djangoproject.com/en/dev/ref/templates/builtins/…
Показать ещё 2 комментария
44

Если вы правильно разделили разделы страницы, вы можете легко использовать теги angularjs в области "raw".

В jinja2

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

В шаблоне Django (выше 1.5)

{% verbatim %}    
    // here you can write angularjs template tags.
{% endverbatim %}
  • 1
    Это решение не нарушает совместимость внешних пакетов с принятым ответом.
28

Мы создали очень простой фильтр в 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)
  • 0
    Еще один очень эффективный способ сделать это, однако я бы предпочел изменить теги в одном месте, чем добавить фильтр во многих ...
  • 1
    Как вы создаете фильтр нг? Можете ли вы добавить пример?
Показать ещё 2 комментария
25

Итак, сегодня я получил большую помощь в канале IRC Angular. Оказывается, вы можете легко изменить теги шаблона Angular. Необходимые ниже фрагменты должны быть включены после включения 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, которые могут быть настроены на любые теги, которые вы хотите.

  • 17
    и вот как вы делаете это в angularjs 1.0: var m = angular.module ('myApp', []); m.config (function ($ interpolateProvider) {$ interpolateProvider.startSymbol ('(('); $ interpolateProvider.endSymbol ('))');});
  • 0
    Угловой канал IRC. к кому бы то ни было, я нашел один в #angularjs
16

Я проголосовал против использования двойных круглых скобок (()) в качестве тега шаблона. Он может работать хорошо, пока вызов функции не задействован, но когда вы попробовали следующее

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

с Firefox (10.0.2) на Mac Я получил ужасно длинную ошибку вместо предполагаемой логики. < [] > прошел хорошо для меня, по крайней мере, до сих пор.

Изменить 2012-03-29: Обратите внимание, что $invalidWidgets устарело. Однако я бы использовал еще одну оболочку, чем двойные фигурные скобки. Для любой версии angular выше 0.10.7 (я думаю) вы можете изменить обертку намного проще в определении вашего приложения/модуля:

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

API docs.

  • 0
    Честная оценка. Я не думал об этом, но я не особо рекомендовал использовать (()) , я просто хотел иметь возможность настраивать разделители.
14

Я нашел код ниже полезным. Я нашел здесь код: 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)
  • 0
    Я использовал этот пользовательский тег, но затем, если я использую что-то вроде: <p>{% ng location %}</p> он будет отображаться как {{location}} - да с фигурными скобками! Он не отображает значение $ scope.location, которое жестко задано в моем контроллере. Есть идеи, что мне не хватает?
13

Вы всегда можете использовать ng-bind вместо {{}} http://docs.angularjs.org/api/ng/directive/ngBind

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

Если вы используете django 1.5 и более новые версии:

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

Если вы застряли с django 1.2 в appengine, расширьте синтаксис django командой verbatim template, подобной этой...

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

  • 0
    Спасибо ... наконец-то все заработало, но мне пришлось ... 1) создать новый модуль Python. Я назвал его утилитой и поместил в него файл verbatim_templatetag.py. (Файл выше с определенным в нем классом VerbatimNode). 2) Измените оператор импорта из: from django import template на: from google.appengine._internal.django import template Затем в моем главном файле просто изменили имя файла: template.register_template_library('utilities.verbatim_template_tag')
8

Для AngularJS v1.3.3 вы должны определить свои собственные теги шаблонов, такие как

Модуль AngularJS

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

страница

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

Вы можете указать Django для вывода {{ и }}, а также других зарезервированных строк шаблонов с помощью тега {% templatetag %}.

Например, использование {% templatetag openvariable %} будет выводить {{.

  • 3
    Я знаю, что это возможно, но это грязно ... Было бы намного чище (и не кажется слишком большой просьбой), чтобы тег шаблона просто настраивался в одной из платформ. В конце концов, это просто сопоставление строк за кулисами ...
3

Я бы придерживался решения, которое использует как теги django {{}}, так и angularjs {{}} с дословным разделом или templatetag.

Это просто потому, что вы можете изменить способ работы angularjs (как упоминалось) через $interpolateProvider.startSymbol $interpolateProvider.endSymbol, но если вы начнете использовать другие компоненты angularjs, такие как ui-bootstrap, вы обнаружите, что некоторые из шаблонов УЖЕ построены со стандартными метками angularjs {{}}.

Например, посмотрите https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html.

  • 0
    Хорошая точка зрения. Теперь в PyPI есть пакет django-angular, предназначенный для того, чтобы они оба играли вместе, но я не изучал, насколько это облегчает проблему с тегами шаблонов.
0

Если вы выполняете любую интерполяцию на стороне сервера, правильный способ только - это <>

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

Все остальное - вектор XSS.

Это связано с тем, что любые разделители Angular, которые не экранируются Django, могут быть введены пользователем в интерполированную строку; если кто-то устанавливает свое имя пользователя как "{{evil_code}}", Angular будет с радостью запускать его. Если вы используете символ чем escape файлы Django, этого не произойдет.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню