web框架---Bottle

2018-08-26 17:31:16来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

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内置模板、mako、jinja2、cheetah
  • 公共组件,用于提供处理请求相关的信息,如:表单数据、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中可以使用 内置模板系统、mako、jinja2、cheetah等,以内置模板系统为例:

 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

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Django2.0 Python3.7 Learn Second

下一篇:Python 反射-isinstance-issubclass-__str__-__del__