2010-06-02 160 views
4

如果有人能夠幫我開始編寫python模板引擎,可能有可能嗎?我是python的新手,並且學習了我設法在自己的輕量級WSGI服務器上編寫一個MVC框架的語言。Python模板引擎

我已經成功地編寫查找和替換密鑰值的腳本: (顯然,這是我的腳本不如何組織或實施這只是一個例子)

from string import Template 

html = '<html>\n' 
html += ' <head>\n' 
html += ' <title>This is so Cool : In Controller HTML</title>\n' 
html += ' </head>\n' 
html += ' <body>\n' 
html += ' Home | <a href="/hi">Hi ${name}</a>\n' 
html += ' </body>\n' 
html += '<html>' 

Template(html).safe_substitute(dict(name = 'Arturo')) 

我的下一個目標是實現自定義語句,修飾符,函數等(如for'循環),但我不知道是否應該使用另一個我不知道的模塊。我想到正則表達式,但我覺得這樣做不會是一個有效的方式做到這一點

任何幫助表示讚賞,我相信這也會對其他人有用。

謝謝

+0

看看Django:http://code.djangoproject.com/。具體來說,看看這些:http://code.djangoproject.com/svn/django/trunk/django/template/。 – Adam 2010-06-02 07:16:26

+0

我不希望這聽起來粗魯或任何東西,但爲什麼編寫自己的框架時,有大量的已寫入的可用? Django是目前最流行的一個;我建議檢查一下,看看它是如何工作的。 – 2010-06-02 07:43:37

+0

@Adam 您發佈的鏈接(第二個鏈接)非常棒,看到主題中的巨頭如何做,總是很好的。時間讓我做一些研究 – jturo 2010-06-02 09:34:46

回答

18

Python有很多功能強大的模板語言。我更喜歡Jinja2。也請看看MakoGenshi

Mako在三個中是最快的,但它的意識形態允許在模板中有一個複雜的代碼邏輯,這種模式會不時引發MVC違反原則。

genshi有很好的概念,特別是強大的功能是反轉模板的繼承。但三者之間速度最慢,並且實踐表明,其實際功能常常在實際項目中過度消耗。

Jinja2在我個人的意見中是一個金色的中間。由於它使用類似於Django模板和模板語言的語法,因此它很容易擴展,速度很快並且很多人都很熟悉。

+0

+1爲Jinja2! – fabrizioM 2010-06-02 07:49:12

+0

謝謝nailxx。 mako網站顯示:Mako:1.10ms Myghty:4.52ms Cheetah:\t 1.10ms Genshi:11.46ms Django:2.74ms Kid:14.54 ms這很酷,他們花時間比較引擎。我的大腦保留信息的能力非常有限,所以我使用約定來幫助我解決這個問題。只要它不是業務邏輯(我不知道這是你的意思所說的「複雜的代碼邏輯」),我可以在模板中使用代碼邏輯 – jturo 2010-06-02 10:28:08

1

那麼,當我決定像你一樣玩耍時,TDD總是一條好路。

那麼,爲什麼不放棄它呢?

例如,創建一個名爲jturo_template.py寫:

import re 
import unittest 

class JTuroTemplate(object): 
    u"""JTuro's template engine core class""" 
    variable_regex = r'\$\{((.*)(%s)([^}]*))*\}' 
    def __init__(self, string): 
     self.string = string 

    def __repr__(self): 
     pieces = self.string.split() 
     if len(pieces) > 3: 
      head = "%s ..." % " ".join(pieces[:3]) 
     else: 
      head = " ".join(pieces) 

     return u'<JTuroTemplate: "%s">' % (head) 

    def render(self, context): 
     new = unicode(self.string) 

     for key, value in context.items(): 
      variable_name = re.escape(key) 
      regex = re.compile(self.variable_regex % variable_name) 

      for match in regex.findall(new): 
       if match[0]: 
        replacement = match[0].replace(key, repr(value)) 
        new = new.replace('${%s}' % match[0], unicode(eval(replacement))) 

     return new 

class TestJTuroTemplate(unittest.TestCase): 
    def test_repr(self): 
     "a instance will be nicely represented" 
     jt = JTuroTemplate('my template') 
     self.assertEquals(repr(jt), '<JTuroTemplate: "my template">') 

    def test_repr_truncated(self): 
     "the python representation is truncated after 3 words" 

     jt = JTuroTemplate('such a long string template') 
     self.assertEquals(repr(jt), '<JTuroTemplate: "such a long ...">') 

    def test_solves_simple_variables(self): 
     "it solves simple variables" 

     jt = JTuroTemplate('my variable is ${var} == 4') 
     self.assertEquals(jt.render({'var': '4'}), 'my variable is 4 == 4') 

    def test_solves_variables_with_python_code(self): 
     "it solves variables with python code" 

     jt = JTuroTemplate('my variable is ${var + var} == 44') 
     self.assertEquals(jt.render({'var': '4'}), 'my variable is 44 == 44') 

if __name__ == '__main__': 
    unittest.main() 

很抱歉的長期職位,但我認爲你可以試試這個工作流程:

  1. 寫測試失敗
  2. 運行並看它失敗
  3. 編寫代碼測試再次通過
  4. 運行,看它傳遞
+0

感謝你的代碼,這也需要一些學習。我認爲正則表達式是一種可行的方法,但最大的問題是:使用執行大量正則表達式的模板引擎,流量大的網站會變得非常慢嗎?再次感謝Gabriel對你的帖子 – jturo 2010-06-02 11:03:25

4

很好,因爲你說你是一個Python菜鳥,而你書面方式從頭開始一個新的MVC框架和模板引擎的唯一原因,是爲了學習目的,你不應該關心性能恕我直言。

但是如果你決定在生產中加入某些東西,你應該考慮使用已經存在的模板引擎,比如jinja2,mako,genshi等等。

無論如何,如果你要玩,有輕量級web python框架內的一個很好的例子:http://github.com/breily/juno

和光速模板引擎在http://github.com/eklitzke/spitfire

快樂黑客!

+0

以及我不得不承認你有一個點。感謝您的鏈接和腳本。好東西玩和學習。 – jturo 2010-06-04 09:34:24