Skip to main content

· 3 min read

最近生活中都是在寫 Code, 鑽研 boa web server 處理的流程, 打開 Dreamweaver 也越來越少使用 Design View, 感覺自己越來越有軟體工程師的樣子.

這陣子寫的 "一分鐘 TurboGears" 系列,前數篇原本是在春節期間用英文寫成的,後來才決定先用最熟悉的中文來寫.

現在的網頁框架幾乎全部都套用 MVC 模式,將資料模型 (Model), 展示頁面 (View,Template) 分離,以控制邏輯 (Control logic) 來溝通兩者以呈現出設計者的思想。這樣的方式讓架構跟維護都變得更清楚更容易.

然而,在寫動態網頁原型的階段時,一定要一次就套用上 MVC 嗎? 我們在網頁程式早期做的頁面,有幾頁能不做大修改就能留用到最後呢? 我們什麼時候能一次就將資料庫欄位,互相間的關聯性一次設計好呢? 起碼對我來講,這兩個假設都是不可能的.

設計 MVC 程式一般理想的流程是:

設計資料庫欄位 -> 產生資料庫 -> 寫樣板 -> 寫控制邏輯以填入資料 -> 展示

但是在實做上

設計資料庫欄位 -> 產生資料庫 -> 寫樣板 -> 寫控制邏輯 -> 發現問題 -> 修改資料庫欄位 -> 重新產生資料庫

我在 Modeling 時發現,在早期設計階段修改欄位的需求很頻繁,(常有些是 paper design 時沒想到的) 碰到這樣的問題時,除了 update 資料庫,若與資料庫不相容時還得將資料庫刪除,再重新產生.

設計 MVC 程式在第一關就遇到 Modeling 問題,接下來當然很難繼續學下去.

有了方便的網頁程式框架,與動態網頁幾乎可忽略的編譯與重新載入時間的特性,我們當然可以用靈活 (agile) 編程的方式來寫我們的網頁程式.

我想最快速動態資料庫網頁 prototyping 的方法,也許就是像目前的範例這樣子先將 model, view 放一邊,純寫程式碼先掌握正確的控制邏輯吧.

· 3 min read

TurboGears 網頁階層的有兩類,第一類是用 "參數" 來對應網頁階層,第二類是用物件樹結構 (即類別實體) 來對應網頁階層.

  1. 參數對應結構

例如 http://localhost:8080/calcit/4/8 "4", "8" 會被分別當成 calcit 方法的第一,第二個參數傳入,作用等同於 http://localhost:8080/calcit?A=4&B=5

如果 calcit 方法不存在,即連結資料夾名稱沒有對應到方法的話,就會被當成參數傳到最近物件的 default () 中當作參數 (在本例為 TurboGears 預設建立的 Root 物件).

  1. 物件樹結構

另外三種情形都是用物件樹結構的 "類別實體"(instance) 來對應網頁階層。可以實現超過一層的網頁. TurboGears 中會自動建立 Root 類別的實體,我們可以建立其他的類別,然後在 Root 類別中建立其他相關類別的實體.(恩... 要把這個概念寫成文字真不容易) 範例如下:

CASE1: controllers.py 內

在 controllers.py 內編寫多個類別 (class)

0  from turbogears import controllers,expose
1
2 class Subfolder(controllers.RootController):
3 @expose()
4 def index(self):
5 return "I am B"
6 @expose()
7 def C(self):
8 return "I am C"
9
10 class Root(controllers.RootController):
11 @expose()
12 def index(self):
13 return "I am Root"
14 @expose()
15 def A(self):
16 return "I am A"
17 B = Subfolder()

我們在 2~8 行編寫了一個類別,在 Root 類別內第 17 行建立該類別的實體,最後我們會得到像下面的網頁階層樹

   Root
/ A B
C

網頁 localhost/ 跟網頁 localhost/B 的文字是由各自類別的 index () 方法來處理.

CASE2: controllers.py 外 (同目錄):

將 Subfolder 類別存成 subfolder.py , 保存在與 controllers.py 同目錄下. subfolder.py 內容如下:

0  from turbogears import controllers,expose
1
2 class Subfolder(controllers.RootController):
3 @expose()
4 def index(self):
5 return "I am B"
6 @expose()
7 def C(self):
8 return "I am C"

TurboGears 可以從 controllers.py 內調用同目錄下的其他類別

from subfolder import Subfolder
from turbogears import controllers,expose
class Root(controllers.RootController):
@expose()
def index(self):
return "Root"
@expose()
def A(self):
return "I am A"

B = Subfolder()

"from subfolder import Subfolder" 前面小寫的 "subfolder" 是檔名 (subfolder.py), 後面的 Subfolder 是類別名

CASE3: 子目錄下 (子系統)

TurboGears 也可以從 controllers.py 內調用子目錄下的其他類別 (待補)