Django ile AngularJS - Çakışan şablon etiketleri


302

AnjanJS Django ile kullanmak istiyorum, ancak her ikisi {{ }}de kendi şablon etiketleri kullanın . Diğer özel şablon etiketlerini kullanmak için ikisinden birini değiştirmenin kolay bir yolu var mı?


1
Django templatesdizininden yalnızca bir şablon oluşturuyorum , geri kalanını koydum static. Bu şekilde parazit olmaz. Burada yazdığım bir eğitim var: coderwall.com/p/bzjuka/…
Connor Leech

angular2 ve jinja2 arasında veri iletmek nasıl? Herhangi bir yardım
Narendra

@Narendra, bu soru ile ilgili olmayan farklı bir problem. Lütfen arayın ve bir cevap bulamazsanız, yeni bir soru olarak sorun.
Endofhage

Yanıtlar:


299

Açısal 1.0 için, enterpolasyon sembollerini yapılandırmak için $ interpolateProvider apis kullanmanız gerekir: http://docs.angularjs.org/api/ng.$interpolateProvider .

Böyle bir şey hile yapmalıdır:

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

İki şeyi aklınızda bulundurun:

  • sunucu tarafı ve istemci tarafı şablonlarını karıştırmak nadiren iyi bir fikirdir ve dikkatle kullanılmalıdır. Ana sorunlar şunlardır: sürdürülebilirlik (okunması zor) ve güvenlik (çift enterpolasyon yeni bir güvenlik vektörü ortaya çıkarabilir - örneğin, sunucu tarafı ve istemci tarafındaki geçici şablonlar kendi başlarına kaçmak güvenli olsa da, kombinasyonları güvenli olmayabilir).
  • {{ }}şablonlarında kullanılan üçüncü taraf yönergelerini (bileşenleri) kullanmaya başlarsanız , yapılandırmanız onları kıracaktır. ( düzeltme beklemede )

İlk sayı hakkında yapabileceğimiz hiçbir şey olmasa da, insanları uyarmak dışında ikinci sorunu ele almamız gerekiyor.


4
İlk noktanızı (bakım, güvenlik ve sunucu tarafı ile istemci tarafı şablonlarını karıştırmayla ilgili diğer endişeler) açıklamak ister misiniz? Biraz daha açıklama yardımcı olacaktır.
Brian

1
@btlachance - Cevabı genişlettim.
Igor Minar

12
$ İnterpolateProvider, ayarlayıcı olarak kullanıldığında kendini döndürdüğünden, biraz daha kompakt bir sürüm: $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
Mark Rajcok

5
"Düzeltme" kapalı gibi görünüyor. Bu, artık üçüncü taraf bileşenleri kullanmak için güvenli olmadığı anlamına mı geliyor?
Alex Okrushko

1
ham çıkış için $ interpolateProvider'ı güncellemenin herhangi bir yolu var mı? örneğin, {{{foo}}} {{[{foo}]}} oluyor?
tester

122

belki Django şablon etiketini kelimesi kelimesine deneyebilir ve şu şekilde kullanabilirsiniz:

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


Bu çok geçerli bir çözüm olsa da, sunucudaki verilerle görünümlerimi önyüklemek istediğim durumlar var, böylece bu hızlı dağınık olacak. Kullanıcının kullanıcı adı gibi şeyleri düşünün, değişmeyecek, bu yüzden sadece sunucudaki şablona yazacağım, ancak etrafında açısal olarak yazacağım parçalar olabilir.
Endophage

16
Verbatim, sürüm 1.5'ten bu yana Django çekirdek etiketlerinin bir parçasıdır: docs.djangoproject.com/en/dev/ref/templates/builtins/…
Pratyush

11
Django 1.7'de standart etiket kitaplığında olduğu için kelimesi kelimeyi yüklemenize gerek yoktur. Etiketleri yalnızca kendiniz kullanmanız gerekir.
highpost

1
Django varsayılan parantez ayarlarından değiştirmek için bir yol olması güzel olurdu, ama bu da işe yarıyor.
Adrian Lopez

42

Sayfanın bölümlerini düzgün bir şekilde ayırdıysanız "raw" etiketi kapsamındaki angularjs etiketlerini kolayca kullanabilirsiniz.

Jinja2 içinde

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

Django şablonunda (1.5'in üstünde)

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

1
Bu çözüm, dış paketler kabul edilen cevabı uydurarak uyumluluğu bozmaz.
partizanos

30

Biz çok yarattıkDjango 'ng'de, ikisini karıştırmayı kolaylaştıran basit bir filtre :

foo.html:

...
<div>
  {{ django_context_var }}
  {{ 'angularScopeVar' | ng }}
  {{ 'angularScopeFunction()' | ng }}
</div>
...

ngSüzgeç aşağıdaki gibidir:

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)

Bunu yapmak için başka bir çok geçerli yol, ancak ben birçok yerde filtre eklemek yerine tek bir yerde etiketleri değiştirmek istiyorum ...
Endophage

1
Ng filtresini nasıl oluşturuyorsunuz? Bir örnek ekleyebilir misiniz?
Ben Liyanage

Cevap güncellendi. @Endophage Django {{}} çiftlerimden çok daha fazla Açısal {{}} çiftim var , bu yüzden Django olanlarını güncellemeyi tercih ederim.
Wes Alvaro

@WesAlvaro ne yazık ki sadece bir cevabı kabul edebilirim.
Endophage

26

Bu yüzden bugün Açısal IRC kanalında büyük yardım aldım. Angular'ın şablon etiketlerini kolayca değiştirebileceğiniz ortaya çıkıyor. Aşağıda gerekli parçacıkları dahil edilmelidir sonra senin açısal arasında (verilen örnek, görünen e-posta listeleri ve kullanacağı (())yeni şablon etiketleri gibi, kendi için yedek):

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

Ayrıca, ortaya çıkacak bir geliştirmeye startSymbolve endSymbolistediğiniz etiketlere ayarlanabilecek özelliklere işaret ettim .


17
ve bunu angularjs 1.0'da böyle yaparsınız: var m = angular.module ('myApp', []); m.config (function ($ interpolateProvider) {$ interpolateProvider.startSymbol ('(('); $ interpolateProvider.endSymbol ('))');});
idursun

Açısal IRC kanalı. fwiw to whoever, Ben bir tane buldum #angularjs
Shanimal

17

Şablon etiketi olarak çift parantez (()) kullanmaya karşı oy kullanıyorum. İşlev çağrısı yapılmadığı sürece iyi çalışabilir, ancak aşağıdakileri denediğinde

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

Mac'te Firefox (10.0.2) ile, amaçlanan mantık yerine çok uzun bir hata aldım. <[]> benim için iyi gitti, en azından şimdiye kadar.

2012-03-29'u Düzenle: Lütfen $ invalidWidgets'in kullanımdan kaldırıldığını unutmayın. Ancak yine de çift parantez daha başka bir sargı kullanın. 0.10.7'den yüksek herhangi bir açısal sürüm için (sanırım) sarmalayıcıyı uygulama / modül tanımınızda çok daha kolay değiştirebilirsiniz:

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

API dokümanları .


Doğru tespit. Bunu düşünmemiştim ama özellikle savunuculuk yapmıyordum (()), sadece sınırlayıcıları yapılandırabilmek istedim.
Endophage

15

Aşağıdaki kodu yararlı buldum. Kodu burada buldum: 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)

Bu özel etiketi kullandım ama sonra gibi bir şey kullanırsam: gibi <p>{% ng location %}</p> render {{location}}- evet kıvırcık parantez ile! Denetleyicimde kodlanmış olan $ scope.location değerini oluşturmaz. Neyi kaçırdığım hakkında bir fikrin var mı?
Keshav Agrawal


11

Django 1.5 ve daha yenisini kullanıyorsanız:

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

Appengine üzerinde django 1.2 ile sıkışmışsanız, django sözdizimini şöyle verbatim şablon komutuyla uzatın ...

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

Dosyanızda şunları kullanın:

from google.appengine.ext.webapp import template
template.register_template_library('utilities.verbatim_template_tag')

Kaynak: http://bamboobig.blogspot.co.at/2011/09/notebook-using-jquery-templates-in.html


Teşekkürler ... nihayet bu çalışma var ama ... 1) yeni bir Python modülü oluşturmak zorunda kaldı. Bunu utilties olarak adlandırdım ve verbatim_templatetag.py dosyasını içine koydum. (VerbatimNode sınıfında tanımlanan dosyada tanımlanmıştır). 2) İçe aktarma ifadesini: olarak from django import template değiştirin: from google.appengine._internal.django import template Sonra, ana template.register_template_library('utilities.verbatim_template_tag')
Roger

7

Etiketi kullanarak Django'ya çıktı vermesini {{ve }}diğer ayrılmış şablon dizelerini bildirebilirsiniz {% templatetag %}.

Örneğin, kullanma {% templatetag openvariable %}çıktı {{.


3
Bunun mümkün olduğunu biliyorum ama dağınık ... Şablon etiketinin çerçevelerden birinde yapılandırılabilir olması çok daha temiz (ve çok büyük bir soru gibi görünmüyor) olurdu. Günün sonunda sadece perde arkasında dize eşleştirme yapıyor ...
Endophage

3

Hem django etiketleri hem de {{}} yanı sıra angularjs {{}} bir sözlü bölüm veya templatetag kullanan bir çözüm ile sopa.

Bunun nedeni, angularjs'in çalışma şeklini (bahsedildiği gibi) $ interpolateProvider.startSymbol $ interpolateProvider.endSymbol aracılığıyla değiştirebilmenizdir, ancak ui-bootstrap gibi diğer angularjs bileşenlerini kullanmaya başlarsanız, bazı şablonların ZATEN inşa edildiğini göreceksiniz. standart angularjs etiketleriyle {{}}.

Örneğin, https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html adresine bakın .


İyi bir nokta. Şimdi PyPI'de iki oyunu birlikte güzelleştirmeyi amaçlayan django açısal bir paket var, ancak şablon etiketi sorununu ne kadar hafiflettiğine bakmadım.
Endophage

0

Herhangi bir sunucu tarafı enterpolasyonu yaparsanız, bunu yapmanın tek doğru yolu<>

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

Başka bir şey bir XSS vektörüdür.

Bunun nedeni, Django tarafından kaçmayan herhangi bir Açısal sınırlayıcının kullanıcı tarafından enterpolasyonlu dizeye girilebilmesidir; Birisi kullanıcı adını "{{evil_code}}" olarak ayarlarsa, Angular mutlu bir şekilde çalıştırır . Bununla birlikte, Django'dan kaçan bir karakter kullanırsanız , bu olmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.