Python之路【第十八篇】:Web框架們
Python的WEB框架
Bottle
Bottle是一個快速、簡潔、輕量級的基於WSIG的微型Web框架,此框架只由一個 .py 檔案,除了Python的標準庫外,其不依賴任何其他模組。
?1 2 3 4 |
pip install bottle
easy_install bottle
apt - get install python - bottle
wget http: / / bottlepy.org / bottle.py
|
Bottle框架大致可以分為以下部分:
- 路由系統,將不同請求交由指定函式處理
- 模板系統,將模板中的特殊語法渲染成字串,值得一說的是Bottle的模板引擎可以任意指定:Bottle內建模板、
- 公共元件,用於提供處理請求相關的資訊,如:表單資料、cookies、請求頭等
- 服務,Bottle預設支援多種基於WSGI的服務,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 server_names
=
{
'cgi'
: CGIServer,
'flup'
: FlupFCGIServer,
'wsgiref'
: WSGIRefServer,
'waitress'
: WaitressServer,
'cherrypy'
: CherryPyServer,
'paste'
: PasteServer,
'fapws3'
: FapwsServer,
'tornado'
: TornadoServer,
'gae'
: AppEngineServer,
'twisted'
: TwistedServer,
'diesel'
: DieselServer,
'meinheld'
: MeinheldServer,
'gunicorn'
: GunicornServer,
'eventlet'
: EventletServer,
'gevent'
: GeventServer,
'geventSocketIO'
:GeventSocketIOServer,
'rocket'
: RocketServer,
'bjoern'
: BjoernServer,
'auto'
: AutoServer,
}
框架的基本使用
?1 2 3 4 5 6 7 8 9 10 11 |
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
bottle import
template, Bottle
root = Bottle()
@root .route( '/hello/' )
def
index():
return "Hello World"
# return template('<b>Hello {{name}}</b>!', name="Alex")
root.run(host = 'localhost' , port = 8080 )
|
一、路由系統
路由系統是的url對應指定函式,當用戶請求某個url時,就由指定函式處理當前請求,對於Bottle的路由系統可以分為一下幾類:
- 靜態路由
- 動態路由
- 請求方法路由
- 二級路由
1、靜態路由
?1 2 3 |
@root .route( '/hello/' )
def
index():
return template( '<b>Hello {{name}}</b>!' , name = "Alex" )
|
2、動態路由
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@root .route( '/wiki/<pagename>' )
def
callback(pagename):
...
@root .route( '/object/<id:int>' )
def
callback( id ):
...
@root .route( '/show/<name:re:[a-z]+>' )
def
callback(name):
...
@root .route( '/static/<path:path>' )
def
callback(path):
return static_file(path, root = 'static' )
|
3、請求方法路由
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@root .route( '/hello/' , method = 'POST' )
def
index():
...
@root .get( '/hello/' )
def
index():
...
@root .post( '/hello/' )
def
index():
...
@root .put( '/hello/' )
def
index():
...
@root .delete( '/hello/' )
def
index():
...
|
4、二級路由
#!/usr/bin/env python # -*- coding:utf-8 -*- from bottle import template, Bottle app01 = Bottle() @app01.route('/hello/', method='GET') def index(): return template('<b>App01</b>!')app01.py
#!/usr/bin/env python # -*- coding:utf-8 -*- from bottle import template, Bottle app02 = Bottle() @app02.route('/hello/', method='GET') def index(): return template('<b>App02</b>!')app02.py ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
bottle import
template, Bottle
from
bottle import
static_file
root = Bottle()
@root .route( '/hello/' )
def
index():
return template( '<b>Root {{name}}</b>!' , name = "Alex" )
from
framwork_bottle import
app01
from
framwork_bottle import
app02
root.mount( 'app01' , app01.app01)
root.mount( 'app02' , app02.app02)
root.run(host = 'localhost' , port = 8080 )
|
二、模板系統
模板系統用於將Html和自定的值兩者進行渲染,從而得到字串,然後將該字串返回給客戶端。我們知道在Bottle中可以使用 內建模板系統、mako、jinja2、cheetah等,以內建模板系統為例:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <h1>{{name}}</h1> </body> </html>hello_template.tpl ?
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
bottle import
template, Bottle
root = Bottle()
@root .route( '/hello/' )
def
index():
# 預設情況下去目錄:['./', './views/']中尋找模板檔案 hello_template.html
# 配置在 bottle.TEMPLATE_PATH 中
return template( 'hello_template.tpl' , name = 'alex' )
root.run(host = 'localhost' , port = 8080 )
|
1、語法
- 單值
- 單行Python程式碼
- Python程式碼快
- Python、Html混合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<h1> 1 、單值< / h1>
{{name}}
<h1> 2 、單行Python程式碼< / h1>
%
s1 = "hello"
<h1> 3 、Python程式碼塊< / h1>
< %
# A block of python code
name =
name.title().strip()
if name
= = "Alex" :
name = "seven"
% >
<h1> 4 、Python、Html混合< / h1>
%
if True :
<span>{{name}}< / span>
%
end
<ul>
% for
item in name:
<li>{{item}}< / li>
% end
< / ul>
|
2、函式
include(sub_template, **variables)
?1 2 3 4 5 |
# 匯入其他模板檔案
%
include( 'header.tpl' , title = 'Page Title' )
Page Content
%
include( 'footer.tpl' )
|
rebase(name, **variables)
<html> <head> <title>{{title or 'No title'}}</title> </head> <body> {{!base}} </body> </html>base.tpl ?
1 2 3 4 |
# 匯入母版
%
rebase( 'base.tpl' , title = 'Page Title' )
<p>Page Content ...< / p>
|
defined(name)
?1 |
# 檢查當前變數是否已經被定義,已定義True,未定義False
|
get(name, default=None)
?1 |
# 獲取某個變數的值,不存在時可設定預設值
|
setdefault(name, default)
?1 |
# 如果變數不存在時,為變數設定預設值
|
擴充套件:自定義函式
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <h1>自定義函式</h1> {{ wupeiqi() }} </body> </html>hello_template.tpl
#!/usr/bin/env python # -*- coding:utf-8 -*- from bottle import template, Bottle,SimpleTemplate root = Bottle() def custom(): return '123123' @root.route('/hello/') def index(): # 預設情況下去目錄:['./', './views/']中尋找模板檔案 hello_template.html # 配置在 bottle.TEMPLATE_PATH 中 return template('hello_template.html', name='alex', wupeiqi=custom) root.run(host='localhost', port=8080)main.py
注:變數或函式前新增 【 ! 】,則會關閉轉義的功能
三、公共元件
由於Web框架就是用來【接收使用者請求】-> 【處理使用者請求】-> 【響應相關內容】,對於具體如何處理使用者請求,開發人員根據使用者請求來進行處理,而對於接收使用者請求和相應相關的內容均交給框架本身來處理,其處理完成之後將產出交給開發人員和使用者。
【接收使用者請求】
當框架接收到使用者請求之後,將請求資訊封裝在Bottle的request中,以供開發人員使用
【響應相關內容】
當開發人員的程式碼處理完使用者請求之後,會將其執行內容相應給使用者,相應的內容會封裝在Bottle的response中,然後再由框架將內容返回給使用者
所以,公共元件本質其實就是為開發人員提供介面,使其能夠獲取使用者資訊並配置響應內容。
1、request
Bottle中的request其實是一個LocalReqeust物件,其中封裝了使用者請求的相關資訊:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
request.headers
請求頭資訊
request.query
get請求資訊
request.forms
post請求資訊
request.files
上傳檔案資訊
request.params
get和post請求資訊
request.GET
get請求資訊
request.POST
post和上傳資訊
request.cookies
cookie資訊
request.environ
環境相關相關
|
2、response
Bottle中的request其實是一個LocalResponse物件,其中框架即將返回給使用者的相關資訊:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
response
response.status_line
狀態行
response.status_code
狀態碼
response.headers
響應頭
response.charset
編碼
response.set_cookie
在瀏覽器上設定cookie
response.delete_cookie
在瀏覽器上刪除cookie
|
例項:
from bottle import route, request @route('/login') def login(): return ''' <form action="/login" method="post"> Username: <input name="username" type="text" /> Password: <input name="password" type="password" /> <input value="Login" type="submit" /> </form> ''' @route('/login', method='POST') def do_login(): username = request.forms.get('username') password = request.forms.get('password') if check_login(username, password): return "<p>Your login information was correct.</p>" else: return "<p>Login failed.</p>"基本Form請求
<form action="/upload" method="post" enctype="multipart/form-data"> Category: <input type="text" name="category" /> Select a file: <input type="file" name="upload" /> <input type="submit" value="Start upload" /> </form> @route('/upload', method='POST') def do_upload(): category = request.forms.get('category') upload = request.files.get('upload') name, ext = os.path.splitext(upload.filename) if ext not in ('.png','.jpg','.jpeg'): return 'File extension not allowed.' save_path = get_save_path_for_category(category) upload.save(save_path) # appends upload.filename automatically return 'OK'上傳檔案
四、服務
對於Bottle框架其本身未實現類似於Tornado自己基於socket實現Web服務,所以必須依賴WSGI,預設Bottle已經實現並且支援的WSGI有:
server_names = { 'cgi': CGIServer, 'flup': FlupFCGIServer, 'wsgiref': WSGIRefServer, 'waitress': WaitressServer, 'cherrypy': CherryPyServer, 'paste': PasteServer, 'fapws3': FapwsServer, 'tornado': TornadoServer, 'gae': AppEngineServer, 'twisted': TwistedServer, 'diesel': DieselServer, 'meinheld': MeinheldServer, 'gunicorn': GunicornServer, 'eventlet': EventletServer, 'gevent': GeventServer, 'geventSocketIO':GeventSocketIOServer, 'rocket': RocketServer, 'bjoern' : BjoernServer, 'auto': AutoServer, }WSGI
使用時,只需在主app執行run方法時指定引數即可:
?1 2 3 4 5 6 7 8 9 10 |
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
bottle import
Bottle
root = Bottle()
@root .route( '/hello/' )
def
index():
return "Hello World"
# 預設server ='wsgiref'
root.run(host = 'localhost' , port = 8080 ,
server = 'wsgiref' )
|
預設server="wsgiref",即:使用Python內建模組wsgiref,如果想要使用其他時,則需要首先安裝相關類庫,然後才能使用。如:
# 如果使用To