web框架---Bottle


Bottle

Bottle是一個快速、簡潔、輕量級的基於WSIG的微型Web框架,此框架只由一個 .py 文件,除了Python的標准庫外,其不依賴任何其他模塊。

1 pip install bottle 2 easy_install bottle 3 apt-get install python-bottle 4 wget http://bottlepy.org/bottle.py

Bottle框架大致可以分為以下部分:

  • 路由系統,將不同請求交由指定函數處理
  • 模板系統,將模板中的特殊語法渲染成字符串,值得一說的是Bottle的模板引擎可以任意指定:Bottle內置模板、makojinja2cheetah
  • 公共組件,用於提供處理請求相關的信息,如:表單數據、cookies、請求頭等
  • 服務,Bottle默認支持多種基於WSGI的服務,如:
 1 server_names = {  2     'cgi': CGIServer,  3     'flup': FlupFCGIServer,  4     'wsgiref': WSGIRefServer,  5     'waitress': WaitressServer,  6     'cherrypy': CherryPyServer,  7     'paste': PasteServer,  8     'fapws3': FapwsServer,  9     'tornado': TornadoServer, 10     'gae': AppEngineServer, 11     'twisted': TwistedServer, 12     'diesel': DieselServer, 13     'meinheld': MeinheldServer, 14     'gunicorn': GunicornServer, 15     'eventlet': EventletServer, 16     'gevent': GeventServer, 17     'geventSocketIO':GeventSocketIOServer, 18     'rocket': RocketServer, 19     'bjoern' : BjoernServer, 20     'auto': AutoServer, 21 }
View Code

框架的基本使用

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from bottle import template, Bottle  4 root = Bottle()  5  
 6 @root.route('/hello/')  7 def index():  8     return "Hello World"
 9     # return template('<b>Hello {{name}}</b>!', name="Alex")
10  
11 root.run(host='localhost', port=8080)

一、路由系統

路由系統是的url對應指定函數,當用戶請求某個url時,就由指定函數處理當前請求,對於Bottle的路由系統可以分為一下幾類:

  • 靜態路由
  • 動態路由
  • 請求方法路由
  • 二級路由

1、靜態路由

1 @root.route('/hello/') 2 def index(): 3     return template('<b>Hello {{name}}</b>!', name="Alex")

2、動態路由

 1 @root.route('/wiki/<pagename>')  2 def callback(pagename):  3  ...  4  
 5 @root.route('/object/<id:int>')  6 def callback(id):  7  ...  8  
 9 @root.route('/show/<name:re:[a-z]+>') 10 def callback(name): 11  ... 12  
13 @root.route('/static/<path:path>') 14 def callback(path): 15     return static_file(path, root='static')

3、請求方法路由

 1 @root.route('/hello/', method='POST')  2 def index():  3  ...  4  
 5 @root.get('/hello/')  6 def index():  7  ...  8  
 9 @root.post('/hello/') 10 def index(): 11  ... 12  
13 @root.put('/hello/') 14 def index(): 15  ... 16  
17 @root.delete('/hello/') 18 def index(): 19     ...

4、二級路由

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from bottle import template, Bottle  4 
 5 app01 = Bottle()  6 
 7 @app01.route('/hello/', method='GET')  8 def index():  9     return template('<b>App01</b>!') 10 
11 app01.py
app01.py
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from bottle import template, Bottle  4 
 5 app02 = Bottle()  6 
 7 
 8 @app02.route('/hello/', method='GET')  9 def index(): 10     return template('<b>App02</b>!') 11 
12 app02.py
app02.py
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from bottle import template, Bottle  4 from bottle import static_file  5 root = Bottle()  6  
 7 @root.route('/hello/')  8 def index():  9     return template('<b>Root {{name}}</b>!', name="Alex") 10  
11 from framwork_bottle import app01 12 from framwork_bottle import app02 13  
14 root.mount('app01', app01.app01) 15 root.mount('app02', app02.app02) 16  
17 root.run(host='localhost', port=8080)

二、模板系統

模板系統用於將Html和自定的值兩者進行渲染,從而得到字符串,然后將該字符串返回給客戶端。我們知道在Bottle中可以使用 內置模板系統、makojinja2cheetah等,以內置模板系統為例:

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title></title>
 6 </head>
 7 <body>
 8     <h1>{{name}}</h1>
 9 </body>
10 </html>
11 
12 hello_template.html
hello_template.html
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from bottle import template, Bottle  4 root = Bottle()  5  
 6 @root.route('/hello/')  7 def index():  8     # 默認情況下去目錄:['./', './views/']中尋找模板文件 hello_template.html
 9     # 配置在 bottle.TEMPLATE_PATH 中
10     return template('hello_template.html', name='alex') 11  
12 root.run(host='localhost', port=8080)

1、語法

  • 單值
  • 單行Python代碼
  • Python代碼快
  • Python、Html混合
 1 <h1>1、單值</h1>
 2 {{name}}  3  
 4 <h1>2、單行Python代碼</h1>
 5 % s1 = "hello"
 6  
 7  
 8 <h1>3、Python代碼塊</h1>
 9 <%
10     # A block of python code
11     name = name.title().strip() 12     if name == "Alex": 13         name="seven"
14 %>
15  
16  
17 <h1>4、Python、Html混合</h1>
18  
19 % if True: 20     <span>{{name}}</span>
21 % end 22 <ul>
23   % for item in name: 24     <li>{{item}}</li>
25   % end 26 </ul>
View Code

2、函數 

include(sub_template, **variables)

1 # 導入其他模板文件
2  
3 % include('header.tpl', title='Page Title') 4 Page Content 5 % include('footer.tpl')

rebase(name, **variables)

 1 <html>
 2 <head>
 3   <title>{{title or 'No title'}}</title>
 4 </head>
 5 <body>
 6  {{!base}}  7 </body>
 8 </html>
 9 
10 base.html
base.html
1 # 導入母版
2  
3 % rebase('base.html', title='Page Title') 4 <p>Page Content ...</p>

defined(name)

1 # 檢查當前變量是否已經被定義,已定義True,未定義False

get(name, default=None)

1 # 獲取某個變量的值,不存在時可設置默認值

setdefault(name, default)

1 # 如果變量不存在時,為變量設置默認值

擴展:自定義函數

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title></title>
 6 </head>
 7 <body>
 8     <h1>自定義函數</h1>
 9  {{ wupeiqi() }} 10 
11 </body>
12 </html>
13 
14 hello_template.html
hello_template.html
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from bottle import template, Bottle,SimpleTemplate  4 root = Bottle()  5 
 6 
 7 def custom():  8     return '123123'
 9 
10 
11 @root.route('/hello/') 12 def index(): 13     # 默認情況下去目錄:['./', './views/']中尋找模板文件 hello_template.html
14     # 配置在 bottle.TEMPLATE_PATH 中
15     return template('hello_template.html', name='alex', wupeiqi=custom) 16 
17 root.run(host='localhost', port=8080) 18 
19 main.py
main.py

注:變量或函數前添加 【 ! 】,則會關閉轉義的功能

三、公共組件

由於Web框架就是用來【接收用戶請求】-> 【處理用戶請求】-> 【響應相關內容】,對於具體如何處理用戶請求,開發人員根據用戶請求來進行處理,而對於接收用戶請求和相應相關的內容均交給框架本身來處理,其處理完成之后將產出交給開發人員和用戶。

【接收用戶請求】

當框架接收到用戶請求之后,將請求信息封裝在Bottle的request中,以供開發人員使用

【響應相關內容】

當開發人員的代碼處理完用戶請求之后,會將其執行內容相應給用戶,相應的內容會封裝在Bottle的response中,然后再由框架將內容返回給用戶

所以,公共組件本質其實就是為開發人員提供接口,使其能夠獲取用戶信息並配置響應內容。

1、request

Bottle中的request其實是一個LocalReqeust對象,其中封裝了用戶請求的相關信息:

 1 request.headers  2  請求頭信息  3  
 4 request.query  5  get請求信息  6  
 7 request.forms  8  post請求信息  9  
10 request.files 11  上傳文件信息 12  
13 request.params 14  get和post請求信息 15  
16 request.GET 17  get請求信息 18  
19 request.POST 20  post和上傳信息 21  
22 request.cookies 23  cookie信息 24      
25 request.environ 26     環境相關相關
request

2、response

Bottle中的response其實是一個LocalResponse對象,其中框架即將返回給用戶的相關信息:

 1 response  2  response.status_line  3  狀態行  4  
 5  response.status_code  6  狀態碼  7  
 8  response.headers  9  響應頭 10  
11  response.charset 12  編碼 13  
14  response.set_cookie 15  在瀏覽器上設置cookie 16          
17  response.delete_cookie 18         在瀏覽器上刪除cookie
response

實例:

 1 from bottle import route, request  2 
 3 @route('/login')  4 def login():  5     return '''
 6  <form action="/login" method="post">  7  Username: <input name="username" type="text" />  8  Password: <input name="password" type="password" />  9  <input value="Login" type="submit" /> 10  </form> 11     '''
12 
13 @route('/login', method='POST') 14 def do_login(): 15     username = request.forms.get('username') 16     password = request.forms.get('password') 17     if check_login(username, password): 18         return "<p>Your login information was correct.</p>"
19     else: 20         return "<p>Login failed.</p>"
21 
22 基本Form請求
基本Form請求
 1 <form action="/upload" method="post" enctype="multipart/form-data">
 2   Category:      <input type="text" name="category" />
 3   Select a file: <input type="file" name="upload" />
 4   <input type="submit" value="Start upload" />
 5 </form>
 6 
 7 
 8 @route('/upload', method='POST')  9 def do_upload(): 10     category   = request.forms.get('category') 11     upload     = request.files.get('upload') 12     name, ext = os.path.splitext(upload.filename) 13     if ext not in ('.png','.jpg','.jpeg'): 14         return 'File extension not allowed.'
15 
16     save_path = get_save_path_for_category(category) 17     upload.save(save_path) # appends upload.filename automatically
18     return 'OK'
19 
20 上傳文件
上傳文件

四、服務

對於Bottle框架其本身未實現類似於Tornado自己基於socket實現Web服務,所以必須依賴WSGI,默認Bottle已經實現並且支持的WSGI有:

 1 server_names = {  2     'cgi': CGIServer,  3     'flup': FlupFCGIServer,  4     'wsgiref': WSGIRefServer,  5     'waitress': WaitressServer,  6     'cherrypy': CherryPyServer,  7     'paste': PasteServer,  8     'fapws3': FapwsServer,  9     'tornado': TornadoServer, 10     'gae': AppEngineServer, 11     'twisted': TwistedServer, 12     'diesel': DieselServer, 13     'meinheld': MeinheldServer, 14     'gunicorn': GunicornServer, 15     'eventlet': EventletServer, 16     'gevent': GeventServer, 17     'geventSocketIO':GeventSocketIOServer, 18     'rocket': RocketServer, 19     'bjoern' : BjoernServer, 20     'auto': AutoServer, 21 } 22 
23 WSGI
WSGI

使用時,只需在主app執行run方法時指定參數即可:

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from bottle import Bottle  4 root = Bottle()  5  
 6 @root.route('/hello/')  7 def index():  8     return "Hello World"
 9 # 默認server ='wsgiref'
10 root.run(host='localhost', port=8080, server='wsgiref')

默認server="wsgiref",即:使用Python內置模塊wsgiref,如果想要使用其他時,則需要首先安裝相關類庫,然后才能使用。如:

 1 # 如果使用Tornado的服務,則需要首先安裝tornado才能使用
 2 
 3 class TornadoServer(ServerAdapter):  4     """ The super hyped asynchronous server by facebook. Untested. """
 5     def run(self, handler): # pragma: no cover
 6         # 導入Tornado相關模塊
 7         import tornado.wsgi, tornado.httpserver, tornado.ioloop  8         container = tornado.wsgi.WSGIContainer(handler)  9         server = tornado.httpserver.HTTPServer(container) 10         server.listen(port=self.port,address=self.host) 11  tornado.ioloop.IOLoop.instance().start() 12 
13 bottle.py源碼
bottle.py源碼

PS:以上WSGI中提供了19種,如果想要使期支持其他服務,則需要擴展Bottle源碼來自定義一個ServerAdapter

更多參見:http://www.bottlepy.org/docs/dev/index.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM