AngularJS dengan Django - Tag templat yang bertentangan

302

Saya ingin menggunakan AngularJS dengan Django namun keduanya digunakan {{ }}sebagai tag templat. Apakah ada cara mudah untuk mengubah salah satu dari keduanya untuk menggunakan tag templating khusus lainnya?

Endofag
sumber
1
Saya hanya membuat satu template dari templatesdirektori Django , sisanya saya masukkan static. Dengan begitu Anda tidak mengalami gangguan. Ada tutorial yang saya tulis di sini: coderwall.com/p/bzjuka/…
Connor Leech
bagaimana cara melewatkan data antara angular2 dan jinja2? Apa pun bantuan
Narendra
@ Narendra itu masalah yang berbeda tidak relevan dengan pertanyaan ini. Silakan mencarinya dan jika Anda tidak menemukan jawaban, tanyakan sebagai pertanyaan baru.
Endophage

Jawaban:

299

Untuk Angular 1.0 Anda harus menggunakan apis $ interpolateProvider untuk mengkonfigurasi simbol interpolasi: http://docs.angularjs.org/api/ng.$interpolateProvider .

Sesuatu seperti ini harus melakukan trik:

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

Ingatlah dua hal:

  • mencampur templat sisi server dan sisi klien jarang merupakan ide yang baik dan harus digunakan dengan hati-hati. Masalah utama adalah: rawatan (sulit dibaca) dan keamanan (interpolasi ganda dapat mengekspos vektor keamanan baru - misalnya, sementara melarikan diri dari sisi server dan sisi klien yang aman sendiri mungkin aman, kombinasi mereka mungkin tidak).
  • jika Anda mulai menggunakan arahan pihak ketiga (komponen) yang digunakan {{ }}dalam template mereka maka konfigurasi Anda akan merusaknya. ( perbaiki tertunda )

Meskipun tidak ada yang dapat kita lakukan tentang masalah pertama, kecuali untuk memperingatkan orang, kita perlu mengatasi masalah kedua.

Igor Minar
sumber
4
Maukah Anda menjelaskan poin pertama Anda (pemeliharaan, keamanan, dan masalah lain untuk pencampuran templat sisi-server dan sisi-klien)? Penjelasan lebih sedikit akan sangat membantu.
Brian
1
@ btlachance - Saya memperluas jawabannya.
Igor Minar
12
Karena $ interpolateProvider mengembalikan diri ketika digunakan sebagai setter, inilah versi yang sedikit lebih ringkas: $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
Mark Rajcok
5
Sepertinya "perbaikan" ditutup. Apakah itu berarti sekarang tidak aman untuk menggunakan komponen pihak ketiga?
Alex Okrushko
1
cara apa pun untuk juga memperbarui $ interpolateProvider untuk output mentah? misalnya {{{foo}}} menjadi {{[{foo}]}}?
tester
122

Anda mungkin dapat mencoba tag template Django kata demi kata dan menggunakannya seperti ini:

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

Bessoufi Mounir
sumber
Walaupun itu solusi yang sangat valid, ada beberapa kasus di mana saya ingin dapat mem-bootstrap pandangan saya dengan data dari server sehingga ini akan cepat berantakan. Pikirkan hal-hal seperti nama pengguna, itu tidak akan berubah jadi saya hanya akan menuliskannya di templat di server tetapi mungkin ada bagian di sekitarnya yang akan saya tulis dengan sudut.
Endophage
16
Verbatim adalah bagian dari tag inti Django sejak versi 1.5: docs.djangoproject.com/en/dev/ref/templates/builtins/…
Pratyush
11
Dalam Django 1.7 Anda tidak perlu memuat kata demi kata karena itu ada di perpustakaan tag standar. Anda hanya perlu menggunakan tag itu sendiri.
Highpost
1
Akan menyenangkan memiliki cara untuk mengubah kurung default Django dari pengaturan, tetapi ini juga berfungsi.
Adrian Lopez
42

Jika Anda melakukan pemisahan bagian halaman dengan benar maka Anda dapat dengan mudah menggunakan tag angularjs dalam lingkup tag "mentah".

Dalam jinja2

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

Dalam template Django (di atas 1,5)

{% verbatim %}    
    // here you can write angularjs template tags.
{% endverbatim %}
terima kasihcatatan
sumber
1
Solusi ini tidak merusak kompatibilitas iwht paket eksternal seperti jawaban yang diterima.
partizanos
30

Kami membuat filter yang sangat sederhana di Django 'ng' yang membuatnya mudah untuk mencampur keduanya:

foo.html:

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

The ngFilter terlihat seperti ini:

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)
Wes Alvaro
sumber
Cara lain yang sangat valid untuk melakukannya, namun saya lebih suka mengubah tag di satu tempat daripada menambahkan filter di banyak ...
Endophage
1
Bagaimana Anda membuat filter ng? Bisakah Anda menambahkan contoh?
Ben Liyanage
Jawaban yang diperbarui. @Eofophage Saya memiliki lebih banyak pasangan {{}} sudut daripada pasangan Django {{}}, jadi saya lebih suka memperbarui pasangan Django.
Wes Alvaro
@WesAlvaro sayangnya saya hanya bisa menerima satu jawaban.
Endophage
26

Jadi saya mendapat bantuan besar di saluran IRC Angular hari ini. Ternyata Anda dapat mengubah tag templat Angular dengan sangat mudah. Cuplikan yang diperlukan di bawah ini harus dimasukkan setelah sudut Anda dimasukkan (contoh yang diberikan muncul di milis mereka dan akan digunakan (())sebagai tag templat baru, sebagai pengganti milik Anda sendiri):

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

Juga, saya diarahkan ke perangkat tambahan mendatang yang akan mengekspos startSymboldan endSymbolproperti yang dapat diatur ke tag apa pun yang Anda inginkan.

Endofag
sumber
17
dan ini adalah bagaimana Anda melakukannya di angularjs 1.0: var m = angular.module ('myApp', []); m.config (function ($ interpolateProvider) {$ interpolateProvider.startSymbol ('(('); $ interpolateProvider.endSymbol ('))');});});
idursun
Saluran IRC sudut. Bagi siapa pun, saya menemukan satu di #angularjs
Shanimal
17

Saya memilih menentang menggunakan tanda kurung ganda (()) sebagai tag templat. Ini dapat bekerja dengan baik selama tidak ada panggilan fungsi yang terlibat tetapi ketika mencoba yang berikut ini

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

dengan Firefox (10.0.2) di Mac Saya mendapatkan kesalahan yang sangat panjang, bukan logika yang dimaksud. <[]> berjalan dengan baik untuk saya, setidaknya sampai sekarang.

Edit 2012-03-29: Harap perhatikan bahwa $ invalidWidgets sudah tidak digunakan lagi. Namun saya masih menggunakan pembungkus lain dari kawat gigi ganda. Untuk versi bersudut lebih tinggi dari 0.10.7 (saya kira) Anda dapat mengubah pembungkus lebih mudah dalam definisi aplikasi / modul Anda:

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

API API .

Lukas Bünger
sumber
Titik adil. Saya tidak memikirkan hal itu tetapi saya tidak secara khusus menganjurkan penggunaan (()), saya hanya ingin dapat mengkonfigurasi pembatas.
Endophage
15

Saya menemukan kode di bawah ini bermanfaat. Saya menemukan kode di sini: 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)
nu everest
sumber
Saya memang menggunakan tag khusus ini tetapi kemudian jika saya menggunakan sesuatu seperti: <p>{% ng location %}</p> itu diberikan sebagai {{location}}- ya dengan kurung kurawal! Itu tidak membuat nilai $ scope.location yang hardcoded di controller saya. Ada yang tahu apa yang saya lewatkan?
Keshav Agrawal
11

Jika Anda menggunakan Django 1.5 dan penggunaan yang lebih baru:

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

Jika Anda terjebak dengan Django 1.2 di appengine memperpanjang sintaks Django dengan perintah template verbatim seperti ini ...

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

Dalam penggunaan file Anda:

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

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

kucing
sumber
Terima kasih ... akhirnya berhasil tetapi saya harus ... 1) membuat modul Python baru. Saya menamakannya utilties dan memasukkan file verbatim_templatetag.py di dalamnya. (File di atas dengan kelas VerbatimNode didefinisikan di dalamnya). 2) Ubah pernyataan impor dari: from django import template ke: from google.appengine._internal.django import template Kemudian, di file utama saya, baru saja mengubah nama file: template.register_template_library('utilities.verbatim_template_tag')
Roger
7

Anda dapat memberi tahu Django untuk menampilkan {{dan }}, serta string templat yang disediakan lainnya dengan menggunakan {% templatetag %}tag.

Misalnya, menggunakan {% templatetag openvariable %}keluaran akan {{.

Thomas Orozco
sumber
3
Saya tahu itu mungkin tapi ini berantakan ... Ini akan jauh lebih bersih (dan sepertinya tidak terlalu besar untuk ditanyakan) agar tag template dapat dengan mudah dikonfigurasi di salah satu kerangka kerja. Pada akhir hari itu hanya melakukan pencocokan string di belakang layar ...
Endophage
3

Saya akan tetap dengan solusi yang menggunakan tag django {{}} dan juga angularjs {{}} dengan bagian verbatim atau templatetag.

Itu hanya karena Anda dapat mengubah cara kerja angularjs (sebagaimana disebutkan) melalui $ interpolateProvider.startSymbol $ interpolateProvider.endSymbol tetapi jika Anda mulai menggunakan komponen angular lain seperti ui-bootstrap Anda akan menemukan bahwa beberapa templat sudah SUDAH dibangun dengan tag sudut standar {{}}.

Sebagai contoh, lihat https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html .

silviud
sumber
Poin yang bagus. Sekarang ada paket django-angular di PyPI yang dimaksudkan untuk membuat keduanya bermain bagus bersama, tapi saya belum melihat seberapa jauh hal ini mengurangi masalah tag templat.
Endophage
0

Jika Anda melakukan interpolasi sisi server, satu - satunya cara yang benar untuk melakukannya adalah dengan<>

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

Yang lainnya adalah vektor XSS.

Ini karena setiap pembatas sudut yang tidak lolos oleh Django dapat dimasukkan oleh pengguna ke string yang diinterpolasi; jika seseorang menetapkan nama pengguna mereka sebagai "{{evil_code}}", Angular akan dengan senang hati menjalankannya . Namun, jika Anda menggunakan karakter daripada Django lolos , ini tidak akan terjadi.

Dan
sumber