web-dev-qa-db-ja.com

AngularJSとDjango-テンプレートタグの競合

DjangoでAngularJSを使用したいのですが、両方ともテンプレートタグとして{{ }}を使用します。他のカスタムテンプレートタグを使用するために2つのうちの1つを変更する簡単な方法はありますか?

298
Endophage

Angular 1.0の場合、$ interpolateProvider apiを使用して補間シンボルを構成する必要があります: http://docs.angularjs.org/api/ng.$interpolateProvider

このような何かがトリックを行う必要があります:

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

次の2つのことに留意してください。

  • サーバー側とクライアント側のテンプレートを混在させることはめったに良いアイデアではないため、注意して使用する必要があります。主な問題は次のとおりです:保守性(読みにくい)とセキュリティ(二重補間は新しいセキュリティベクトルを公開する可能性があります-たとえば、サーバーサイドとクライアントサイドのテンプレートをエスケープすること自体は安全かもしれませんが、それらの組み合わせは安全ではないかもしれません)。
  • テンプレートで{{ }}を使用するサードパーティのディレクティブ(コンポーネント)の使用を開始すると、設定によってそれらが壊れます。 ( 修正保留中

最初の問題についてできることは何もありませんが、人々に警告することを除いて、2番目の問題に対処する必要があります。

296
Igor Minar

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

ページのセクションを適切に分離した場合、「raw」タグスコープでanglejsタグを簡単に使用できます。

Jinja2で

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

Djangoテンプレート(1.5以上)

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

Django 'ng'にveryシンプルフィルターを作成し、2つを簡単に混合できるようにしました。

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)
29
Wes Alvaro

それで、今日、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プロパティを公開する今後の機能強化についても指摘されました。

26
Endophage

テンプレートタグとして二重かっこ(())を使用することに反対票を投じます。関数呼び出しが含まれていない限りうまく機能する可能性がありますが、次のことを試みたとき

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

mac上のFirefox(10.0.2)では、意図したロジックではなく、ひどく長いエラーが発生しました。少なくとも今までは、<[]>はうまくいきました。

Edit 2012-03-29:$ invalidWidgetsは廃止されることに注意してください。ただし、二重中括弧以外のラッパーを引き続き使用します。 angularバージョンが0.10.7より高い場合(推測)、アプリ/モジュール定義でラッパーをはるかに簡単に変更できます。

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

APIドキュメント

17
Lukas Bünger

以下のコードが役に立ちました。ここでコードを見つけました: 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)
15
nu everest

{{}}の代わりにng-bindを常に使用できます http://docs.angularjs.org/api/ng/directive/ngBind

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

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

11
cat

AngularJS v1.3.3の場合、このような独自のテンプレートタグを定義する必要があります

AngularJSモジュール

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

ウェブページ

<a>{$ variable $}</a> 
9
Alex Jolig

{{ タグを使用すると、Djangoに}}{% templatetag %}のほか、予約済みの他のテンプレート文字列を出力するように指示できます。

たとえば、{% templatetag openvariable %}を使用すると、{{が出力されます。

7
Thomas Orozco

Djangoタグ{{}}とverbjs {{}}の両方を逐語的なセクションまたはテンプレートタグの両方で使用するソリューションに固執します。

これは、単に$ interpolateProvider.startSymbol $ interpolateProvider.endSymbolを使用して、angularjsの動作を変更できるためです(ただし、ui-bootstrapなどの他のanglejsコンポーネントの使用を開始すると、テンプレートの一部が既にビルドされていることがわかります)標準のanglejsタグ{{}}を使用します。

たとえば、 https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html をご覧ください。

3
silviud

サーバー側の補間を行う場合、onlyこれを行う正しい方法は<>を使用することです

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

それ以外はXSSベクトルです。

これは、AngularによってエスケープされないDjango区切り文字は、ユーザーが補間された文字列に入力できるためです。誰かが自分のユーザー名を「{{evil_code}}」に設定すると、 Angularは喜んで実行します 。ただし、 Djangoエスケープよりも大きい文字 を使用すると、これは起こりません。

0
Dan