pylons - web 開發瑞士刀
DESCRIPTION
簡要地介紹 Pylons 這個基於 Python 的精簡網站開發框架,以及用它來做測試先行的模樣。TRANSCRIPT
i work in tainan in 2008
i quest in pylons from 2007
i play python since 2006
Why Python?
工藝
* 需求 * 規格
* 工具 * 文件
* 人員 * 速度
* 變化
Why Pylons?
PycTW 2008 都過了半年有怎麼我還在 Pylons snolyP ?
彼節者有閒,而刀刃者無厚;以無厚入有閒,
恢恢乎其於遊刃必有餘地矣,以是十九年而刀刃若新發於硎。
利器
* WSGI* Paster* Routes* Beaker* Mako
* SQLAlchemy* WebHelpers
新發於硎
Pylons 0.8 (2005-2006)
Python 開發框架 (Framework) (30+) 的年代 Ben Bangert & James Gardner
基於 Myghty 的 Python 模版 (Templating)MVC 框架WSGI 規格
Web 應用堆疊 (stack)
動手
老師說
安裝
要重視環境清潔
go-pylons.py
建立一個虛擬Python環境相關套件安裝在其之下
% curl -C - -O \http://www.pylonshq.com/download/0.9.7/go-pylons.py
% python go-pylons.py kaenv
歡迎來到卡陰虛擬世界% cd kaenv
% source bin/activate
建立你的 Project
稱之卡后% paster create --template=pylons kaho
(or paster create -t pylons kaho)
Selected and implied templates: Pylons#pylons Pylons application template
Variables: egg: kaho package: kaho project: kaho Enter template_engine (mako/genshi/jinja2/etc: Template language) ['mako']: Enter sqlalchemy (True/False: Include SQLAlchemy 0.4 configuration) [False]:
egg, package, project: 將來良心發現回頭來打包 egg package 時用
mako: 用於 pylons 的模版語言
SQLAlchemy: 支援許多資料庫的 ORM 套件
跑不跑得起來?
% cd kaho% paster serve --reload development.ini
# development.ini: # 執行環境設定,如 debug mode# 也在此可更改下頁的 127.0.0.1 與 5000# --reload: 程式一有所更動即 reload system
Starting subprocess with file monitor Starting server in PID 16806. serving on http://127.0.0.1:5000
% tree kaho kaho |-- development.ini |-- test.ini |-- setup.cfg |-- setup.py |-- docs |-- kaho | |-- config | | |-- deployment.ini_tmpl | | |-- environment.py | | |-- middleware.py | | `-- routing.py | |-- controllers Controller | | `-- error.py
| |-- lib | | |-- app_globals.py | | |-- base.py | | `-- helpers.py | |-- model Model | | `-- __init__.py | |-- public | | |-- index.html | | `-- ... | |-- templates View
| |-- tests | | |-- __init__.py | | |-- functional | | `-- test_models.py | `-- websetup.py |-- kaho.egg-info | `-- ... |-- ez_setup.py `-- README.txt
% paster controller kagin
產生一個卡緊 ControllerCreating .../kaho/controllers/kagin.py
Creating .../kaho/tests/functional/test_kagin.py
註:如果你知道 controllers/xxx.py 的樣子,你也可以自己建立; test_xxx.py 是選擇性的檔案,但建議使用,增加程式穩定度。
先來咬一口 Test Driving
tests/functional/test_kagin.py
from kaho.tests import *
class TestKaginController(TestController):
def test_index(self): response = self.app.get(url(controller='kagin', action='index')) # Test response... assert 'jogin' in response
% nosetests kaho/tests/functional/test_kagin.py
# path is relative with test.ini & development.ini
F =================================================FAIL: test_index (kaho.tests.functional.test_kagin.TestKaginController) -------------------------------------------------Traceback (most recent call last): File "kaho/tests/functional/test_kagin.py", line 8, in test_index assert 'jogin' in responseAssertionError -------------------------------------------------Ran 1 test in 0.005sFAILED (failures=1)
controllers/kagin.py
class KaginController(BaseController):
def index(self): # Return a rendered template #return render('/kagin.mako') # or, return a response return 'Hello World, Jinja jogin?'
% nosetests kaho/tests/functional/test_kagin.py. ---------------------------------------------Ran 1 test in 0.005s
OK
index.html
* WSGI* Paster* Routes* Beaker* Mako
* SQLAlchemy* WebHelpers
What The File?
% rm kaho/public/index.html
Error?
config/routing.py
"""Routes 設定
更特別而細部的路由應定先定義,使其在一般路由之前先被觸發。參考 routes 手冊以獲得更多資訊: http://routes.groovie.org/docs/"""from pylons import configfrom routes import Mapper...
config/routing.py
# ErrorController route # ( 處理 404/500 錯誤頁面 ) 應該保持在最上方 # 以確保它能被處理 map.connect('/error/{action}', controller='error') map.connect('/error/{action}/{id}', controller='error')
config/routing.py
# 客製 ROUTES 於此 map.connect('/', controller='kagin', action='index') map.connect('/{controller}/', action='index')
map.connect('/{controller}/{action}') map.connect('/{controller}/{action}/{id}')
return map
最後一眼? http://127.0.0.1:5000
回顧
* WSGI* Paster* Routes* Beaker* Buffet* Mako
* SQLAlchemy* WebHelpers
Paster
Threaded HTTP Server WSGI Server
* HTTP Request 調配 (dispatching) 、鏈結 (chaining)* 除錯 (debuggin) 、 logging , 以及例外處理 (exception handling)
# 更多資訊: http://pythonpaste.org/script/
Routes
Ruby 風的路由m.connect('spam/:year/:month/:day')
* 允許預設值* 允許建立 URL h.link_to('my love', url(controller='i', action='choose'))* 允許命名路由 h.link_to('your love', url('who_knows'))
c & Session
更深一點Harder! Harder!
c controllers/kagin.py
def index(self): c.love = "you dream" return render('/index.html')
templates/index.html
<h1> ${c.love}
</h1>
session
templates/login.html
${h.link_to('login', '/kagin/login')} ${h.link_to('login2', url(controller='kagin', action='login'))} ${h.link_to('login3', url('login'))}
lib/helper.py
from webhelpers.htmp.tags import link_to
WebHelpers
一些對 Web App 方便的函式* HTML 標籤產生、頁數產生等* >>> h.text('username') literal( u'<input id="username" name="username" type="text" />') >>> h.password('password') literal( u'<input id="password" name="password" type="password" />')
controllers/kagin.py
def login(self): if 'times' in session: session['times'] += 1 else: session['times'] = 1 session.save() return render('login.html')
templates/login.html
<h1> Login </h1> 進入了多少次? ${session['times']}
config/routing.py
#login2map.connect('login', '/kagin/ginsa', controller='kagin', action='login')
#login3, 取代了 'login' 的定義map.connect('login', '/kagin/login')
#loginmap.connect('/{controller}/{action}')
Test Time
tests/functional/test_kagin.py
import sysimport logging...def test_login(self): response = self.app.get( url(controller='kagin', action='login')) ...
tests/functional/test_kagin.py
... # print out in tests, stype a print >> sys.stderr, '' # print out in tests, stype b logging.warn(response.session['times']) assert not response.session.has_key('times')
# 更多關於 tests in pylons: # http://pylonshq.com/docs/en/0.9.7/testing/
Beaker
Session 管理* 支援數種不同形態的 cache 後端: memory, filesystem, memcached 及 database Database 形態後端目前支援: SQLite, SQLAlchemy 及 Google BigTable
# 更多資訊: http://www.pylonshq.com/docs/en/0.9.7/sessions/#beaker
遺珠簡介
WSGI
# encoding:utf-8
def app(environ, start_response): start_response('200 OK', [('content-type', 'text/html')]) #辭鍵 return ['Hello world!', 'Hello hell']
if __name__ == '__main__': from paste import httpserver httpserver.serve(app, host='127.0.0.1', port='8080')
# 可見: http://zh.wikipedia.org/wiki/WSGI
config/
routing.pymiddleware.py:
def make_app(): app = PylonsApp() app = FooMiddleware(app) app = BarMiddleware(app) ...return app
environment.py
lib/
base.py:BaseControllerdef __before__(self): abort(404)
helpers.pyapp_globals.py
setup.cfg
[nosetests]with-pylons = test.iniVerbosity=2 (0, 1, 2, 3, 4)
SQLAlchemy
當前 Python 最強大的 ORM (Object-relational mapping) 套件之一。
可對應於 SQLite, Postgres, MySQL, Oracle, MS-SQL, Firebird, MaxDB, MS Access, Sybase 及 Informix ; IBM 也釋出了它的 DB2 adapter(放在 Google Code 上 ) 。
可說是能一路從留言版玩到 ERP 的玩意兒。
# http://www.sqlalchemy.org/
Nice supports
I18n Helpers (&Babel)Form Generation & Validation (&FormEncode)
...
Nice Supported
FormAlchemy (.pylons)repoze.what (.pylons)
Toscawidgets (pylons examples)Turbogears (about pylons)
...
更多神兵利器
1. Models :SQLAlchemy , Storm , CouchDB ,或什麼都不用2. Templating :Mako , Genshi , Jinja2 ,或其它你喜歡的3. Helpers :WebHelpers 可用於小型的 HTML 片段, FormAlchemy 可產生整個資料庫的表單 (All Together CRUD?)
展望未來
如果還有明天
Pylons 1.0 及之後 (2009-)
1.0目標是成為完整而精鋉的 Web 應用框架。
目前預測是在 2009 前半年間釋出 Pylons 1.0 。
變形蟲的潛力?
* Tuborgears 2 "the built on top of the experience of several next generation web frameworks including TurboGears 1 (of course), Django, and Rails." http://turbogears.org/2.0/
* Shabti "A collection of customised project templates for Pylons intended to provide some quick and easy kickstarts for building web applications in Pylons." http://bel-epa.com/shabtidocs/
Question:What do you want?
「我想要開發一個 Web 應用程式?」 go-django.pycommand not found (yet): go-django.py
「一個小中小企業用的 Web ,能在 MVC 部份有充分的 彈性,以因應企業 (幸運地 ) 在未來成長上的變化。」 go-pylons.py
「一個能讓我選擇 ORM 及 Templating ; 甚至 ( 最好不要有 )哪一天,可以改寫替換架構中的 任一部份的框架。」 go-pylons.py
「能提供簡易的 Test-Driving 與 Software-Deploy 。」 go-pylons.py (go-others?)
「老闆,來一份什錦。」 go-dyjantgglonsapp.py (...大家摃死 app ? )you dream