Django 內建的 template

Django 內建的 template 定了一套完整的使用規範:
  • template 內不能 call function, a.b 會視情況解讀成  a.b, a[b], a.b()。所以不管 a 是 dictionary, list 還是其它物件, 「照理說」都能順利地拿到 b 的值。但若 b 是變數的話, 拿不到 a[b]。
  • filter 可以接受一個參數。比方說 my_list|join:', ' 相當於 ', '.join(my_list), 不過這裡的 join 是 Django 定的 template filter。透過 filter 能做到如同 Python function call 傳兩個參數。另外 filter 如預期般可以串起來, 像是 my_list|join:', '|safe。我常用的兩個例子是顯示 verbose_name用變數當 key 取出 dictionary 的值
  • template tag 可以接受多個參數, 想用函式做的事, 它都能做。唯一不同之處, 在於 template tag 定了一套 parse -> new node -> node.render 的流程。不像平時的習慣: 傳參數到函式, 函式直接回傳字串。詳情可以參考官網的說明
若有照 template 的規範寫, 應該能將 model、view (Django 的 controller)、template 切得很乾淨, template 的 helper function 一致放在 templatetags 目錄, 裡面有自制的 filter 和 template tag。但是 template tag 寫起來實在太冗了, 幾行可以搞定的事, 得拆成三個步驟做。另外我懷疑這樣是否會有效能的隱憂。

若沒照 template 的規範寫, 程式碼會變得比沒規範的情況更難懂。傳 class A 的物件 a 給 template 時, 就塞些 template 要用的東西到 a.x, a.y 裡, 而 x, y 不是 a 原始的 member field。或是在 A 裡寫和 A 不是很相關, 不接參數的函式, 目的只是要讓 template 可以取用值。

難怪 Django FAQ 裡有這麼一項: "I can't stand your template language. Do I have to use it?"。看到有人推 Jinja2 Mako。初步掃了一下語法, Jinja2 看起來滿漂亮的, Mako 看起來有點亂, 很像 Python 但又不是 Python。Jinja2 的 filter 可接受多個參數, 又有 macro 的語法, 應該可以輕鬆滿足常用需求。

不過稍微研究一下換 template 的事後, 發現有些 plugin 和內建 template 綁在一起, 如內建的 Django auth 和 django pagination。換用別的 template 就不能直接使用, 得自己用新的 template 改寫。想想還挺麻煩的。各家 template 也會有點小問題, 像 Jinja2 用到 ctypes 加速, Google App Engine 上沒有 ctypes, 造成 Jinja2 無法提供正確的錯誤訊息。還是先繼續用內建的 template 吧。

留言

這個網誌中的熱門文章

(C/C++ ) 如何在 Linux 上使用自行編譯的第三方函式庫

熟悉系統工具好處多多

virtualbox 使用 USB 裝置