Skip to main content

56 posts tagged with "TurboGears"

View All Tags

· 7 min read

許多人以為 TurboGears 能跟 DjangoRuby on Rails 比較的地方只是因為一個分散組件,一個集中開發.

但 TurboGears 好用的地方並不是在它堆砌了許多開源的 python web 專案 (如不曾成功過的 subway), 而是真正提出了一個整合這些 python web 開發資源的方法。並提供相當具有 python 風格 (pythonic) 的使用方式.

1. Decorator 形式的 Dispatcher

TurboGears 的多數的秘密存在於 Decorator (用 "@" 符號開頭的敘述) 中. Decorator 是 python 2.4 後才引入的特性, 適度使用可以讓程式碼更清晰.

TurboGears 基本的網頁型態是這樣:

>
> @expose()
> def index():
> return

基本的 pyhton method 加上 @expose() 這個 decorator 敘述, 讓 server 知道這個函式是 public to web 的.

需要登入認證功能,就再加一個 @identity 敘述

> #auth_admin_required = identity.in_group("admin")
> @identity.require(auth_admin)
> @expose()
> def index():
> return

如此被裝飾到的網頁就有了認證功能.

同樣形式的還有

@paginate # 分頁功能 @validate # 表單驗證功能 @error_handler #錯誤處理功能 @exception_handeler #例外處理功能

等特殊功能.

@validate 表單驗證的功能除了驗證表單參數, 還負責將參數從字串轉換成 python native 格式,可以對網頁傳過來的參數直接用 python 做處理.

@error_handler 和 @exception_handeler 被用來對應表單驗證功能 讓我們可在同一個函式裡處理錯誤,或另外定義函式做錯誤處理

>
> @error_handler("index")
> def ex_report():
> return "exception"

2. 一個函式,多重輸出

很多人知道 TurboGears 在樣板選擇上的多樣性, 但是卻沒有挖掘到在 TurboGears 的神奇之處. 在 TurboGears 中使用同一個函式,就可以針對不同需求,輸出多種期望的格式.

>
> # 使用網頁樣板產生網頁介面
> @expose(template = "hello.welcome")
> # 產生 JSON 格式介面供 AJAX 程式調用
> @expose("json")
> #使用不同的樣板引擎, 產生RSS格式介面
> @expose(template = "genshitext:hello.hoho", as_format="RSS/XML")
> def show(self, **kw):
> return dict(name = 'foo', url = 'boo')

這是因為 TurboGears 回傳使用 python 特殊的 "字典 (dict)" 形式, 而不是一般常見的字串形式 (當然 TurboGears 同樣也可以直接輸出字串).

當使用者要求網頁的時候,web server 決定好對應的 method 運行後, method 輸出字典型式的返回值到 decorator. 再根據 @expose decorator 的判斷條件, 取用適當的樣板配合字典來生成適當的介面.

原本需要自行將樣板與內容 "串連 (serialize)" 的工作,TurboGears 都幫忙我們完成, 讓我們只要專注在程式邏輯上即可.

要從別的 method 調用這個函式不同的輸出也很容易, 只要在返回值裡加上一個 "tg_format" 參數即可手動指定輸出格式.

>
> @expose()
> def rss():
> return rss(tg_format = "RSS/XML")

3. 簡單設定

通常在 TurboGears 中要讓一個資料庫程式運作, 只要在 dev.cfg 裡指定好對應的資料庫路徑 (dburi), 就可以開始資料庫網站的開發. TurboGears 自會幫忙處理初始化的動作,並且提供相應工具.

要改換整個網站的預設樣板引擎,同樣也是一行設定搞定.

tg.defaultview = "genshi"

程式裡往往會有些可以讓使用者修改預設運行設定的地方, 如在程式裡要取得預設的模板引擎,可以使用

> config.get("tg.defaultview")

來取得預設的模板引擎。取得其他設定值也是使用同樣的方法.

TurboGears 開發的應用程式在發佈 / 安裝上相當容易. 使用易用的 setuptools python 套件發佈功能, 安裝時能自動抓取使用到的 python modules.

4. 高擴展性

TurboGears 框架是個組合框架 (meta framework), 因此設計之初就把高擴展性視為重要目標. 只要在 console 中使用 tg-admin info 命令就可以一窺 TurboGears 擴展的面目。你會驚訝地發現其實 TurboGears 大多數的功能都是透過擴展實現.

TurboGears 使用的擴展方式是透過 python setuptools 的 entrypoint, 撰寫自己的擴展並不需要改動 TurboGears 的原始碼. 安裝擴展也可以透過 easy_install 命令自動從 python cheese shop 下載組件.

5. 與 Python 社群互利

TurboGears 並不是一個只取不予的開發框架, 一方面 TurboGears 降低了試用各 python web modules 的難度, 使得各專案能吸引更多使用者,也加快了各專案的成熟度;

另外一方面,除了多數 python modules 都可配合 TurboGears 使用之外, TurboGears 框架中所開發出來的工具也都盡量朝能獨立於框架外使用的方向邁進.

近期的成果是 ToscaWidgets, 將 TurboGears 中方便重用的 widgets 獨立出來, 可在 pylons, web.py 等框架和工具上使用.

TurboGears 在組合框架上,不只是達到功能上的滿足,還達到與 python 語言使用上的一致性. 充分使用各種 python 語言的特性與工具,沒有過多的 Magic. 這是許多追趕的組合框架應該思考的.

PS: 對 Open Source Project 來說,一個好的文件網站也很重要

· One min read

拿到一個現成的資料庫,最快速的就是直接存取啦.

TurboGears 中除了預先定義 schema 外,也可以直接使用 SQLAlchemy 中的 SqlSoup 模組來直接存取資料庫.

之前我有寫過英文版的,今天 trace 一下 sqlsoup 後發現還有更簡單的方法:直接取用 metadata.

1. 修改 dev.cfg 中的 sqlalchemy.dburi , 指到對應的資料庫

2. 在 your project/model.py 中,寫下

from turbogears.database import metadata from sqlalchemy.ext.sqlsoup import SqlSoup

soup = SqlSoup(metadata)

3. 使用 shell 存取資料

$ tg-admin shell

poll = soup.poll.select() print poll

· 2 min read

Purpose

Have an exist database and want migrate to TurboGears? Or you've been using TurboGears SQLObject model and want to migrate to SQLAlchemy?

Solution

TurboGears newly support SQLAlchemy 0.2 module(>0.9a6), it provide a slick solution: SqlSoup !

What SqlSoup does?

SqlSoup inspects your database and reflects its contents to class, no model definitions are necessary!

What does that mean?

It means you only need to specify a uri for database, and call SqlSoup to do the rest.

What's the Benifits?

SqlSoup maps database tables to classes automatically. I'm not sure how efficient it is, but at least you can use SqlSoup by following ways:

  • To use existing Database design tools to design my database
  • To use SqlSoup in design phase, and code to SQLAlchemy class when the databse is settled down.
  • To painless migrate SQLObject generated database to SQLAlchemyTest Code

Try the test code, it is thin.

in model.py

1 from sqlalchemy.ext.sqlsoup import SqlSoup

2 uri = "sqlite://%(current_dir_uri)s/devdata.sqlite" 3 soup = SqlSoup(uri)

Explain

line 1 import SqlSoup from sqlalchemy module,

line 2 specify the uri link to the database (I believe it can be improved)

line 3 the real code calling SqlSoup connect to uri

line 4 and line 5 shows I call the table "poll" from database

if you can't execute is , maybe you should install sqlalchemy first

$ easy_install sqlalchemy

or try the TurboGears way:

1 from turbogears import config 2 from sqlalchemy.ext.sqlsoup import SqlSoup

3 uri = config.get('sqlalchemy.dburi') 4 soup = SqlSoup(uri) All you need to do is specify the dburi for sqlsoup.

Let's test what we got

poll = soup.poll.select() print poll

Reference

That's all you need in TurboGears. To get further usage , you can refer to Introducing SqlSoup

ps: Actually TurboGears has done nothing particularly to support SqlSoup, I just use it as other modules.

· 2 min read

TurboEntity 照著 'SimpleBlog Part II' 中的範例改寫後,獲得以下程式碼 (model.py):

>
> from turboentity import *
> from docutils.core import publish_parts
>
> class Post(Entity):
> class turboentity:
> tablename = "posts"
>
> title = Column(Unicode(50))
> content = Column(Unicode)
> post_date = Column(DateTime, default=datetime.now())
> is_published = Column(Boolean, default=False)
> comments = OneToMany('Comment',backref='posts')
>
> @property
> def html_content(self):
> return publish_parts(self.content,writer_name="html")["html_body"]
>
> class Comment(Entity):
> class turboentity:
> tablename = "comments"
>
> author_name = Column(Unicode(255), nullable=False)
> author_email = Column(Unicode(255), nullable=False)
> author_url = Column(String(255))
> comment_date = Column(DateTime, default=datetime.now())
> content = Column(Unicode)
> post = ManyToOne("Post",backref='comments')
>

要表示 post-comments 關係只需分別在兩個類別中宣告 OneToMany - ManyToOne 即可,真是方便呀.

另外當定義好 TurboEntity 類別後,物件自動可以用傳值的方式輸入內容,不需一個個各別指定喔.

例如一般的寫法是這樣子:

p = Post.get (1) # 取得條目 c = Comment () # 新建一條評論 c.post = p # 這條評論屬於 p 條目 c.author_name = "CommentDude1" # 這條目的作者是 c.author_email = "[email protected]" # 這條目作者的郵件信箱是 c.content = "Great post! Keep them coming!" # 這條目的內容 c.flush () 可以直接改成 p = Post.get (1) c = Comment (post=post, author_name="Bob", author_email="[email protected]", content="Bob loves this site.", author_url="http://bob.example.com/") c.flush()

TurboEntity改寫的程式和原本 Tutorial 相比,可以看出它好用的地方.

· 4 min read

明天公司補放國父誕辰紀念日,所以有空到 Google 翻翻最近有沒什麼有趣的文章。我找到了一篇 TurboGears vs Rails. 文章名稱夠聳動,雖然這篇文章有點舊了 (用的是 0.9 的預覽版 TurboGears, 或稱為未進化型態版本 XD), 不過裡面對 TurboGears 和 Rails 的特性確實抓得頗準:

The Pythonic way is "explicit over implicit". Everything is out for show: you know what modules are imported, you know what methods are exposed, you know what columns are defined and so on. It may take more keystrokes but the extra code let's you know what is happening when things go wrong. python 語言的風格是 '直率的比含糊的好'. 所以所有的過程都可以被檢視:妳曉得如何導入使用的模組,函式怎麼對應到網址上,妳也曉得資料物件如何定義等等。妳可能需要多打一些字 (註:事實上不多), 但是這些額外的程式碼能讓妳在發生錯誤時更容易地知道自己的程式到底發生了什麼事.

The the Rails way is the opposite: take the burden off the developer, don't bother them with the petty details that get in the way and add to the line noise. Rails 的寫作方式則相反:把讓開發者困擾的因子都去除掉,不要在開發中用細節來干擾程式碼.

事實上去年 5 月底時,我在看過 OnLamp 網站上的 Ruby On Rails 教學後,相當驚訝現在網頁開發的進步 (之前有一年沒寫動態網頁了). 所以我也趁等待完成論文前的時間歔空寫了篇 Ruby On Rails 教學。不過在 7 , 8 月 Django, TurboGears 這些 Python 框架相繼出現後,我發現除了可以使用熟悉的 Python 語言風格來寫程式之外,以後也可以透過網頁介面來使用大量的 Python 模組實在非常吸引我。而當 TurboGears 框架出現 ToolBox 這神奇的工具箱後,我開始漸漸投入了 TurboGears 開發的行列.

能展現自我特點的是創意而不是程式碼 在我的觀念裡,能展現自我特點的是創意而不是程式碼 (也許因為我不是個天才程式設計師吧 XD). Rails 也是個相當吸引人的框架 (差不多靠一己之力拉拔 Ruby 語言 XD). 但是 python 的 "應該會有一個 -- 最適當的一個的方式來實現" 哲學比較接近我的想法。在閱讀其他人的 TurboGears 專案時只要不用到太進階的 Python 語言功能,基本上都非常易於閱讀與修改. (例如目前 TurboGears 最進階的教學文件: SQLalchemy 版的 SimpleBlog, 花一些時間就可以改寫成 TurboEntity 版 SimpleBlog 之一, 之二)