web框架---Bottle

发布时间:2019-03-03 09:59:08编辑:auto阅读(2265)

    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

     

关键字

上一篇: Python之简易计算器

下一篇: 异常处理