Bottle 总结
更新日期:
简介
“Bottle是一个快速,简单,轻量级的Python WSGI Web框架。它小巧但高效,整个框架只有一个文件,却自带了路径映射(route)、模板(template)、简单的数据库访问(post,get等)等web框架组件。它只依赖Python标准库。”
- URL映射(Routing):将URL请求映射到Python函数。
- 模板(Templates):内置了一个简单快速的模板引擎,并支持其他模板引擎,如Mako,Jinja2,cheetah等
- 实用工具(Utilities):内置了很多工具来提供表单数据的访问,文件上传,Cookies处理,HTTP头信息处理和访问其他HTTP相关信息的功能.)
- 服务器(Server):Bottle内置了一个用于开发环境的Web服务器,在生产环境下还支持paste,gae,Google App Engine,cherrypy等符合WSGI标准的HTTP服务器。
成熟的web框架应该有:基本HTTP请求处理、GET或POST数据的接受、模板、数据库、session等功能。
可是bottle并没有提供配置文件集成,数据库管理,可扩展的中间件等特性,所以它并不是开发复杂项目的第一选择。对于大型的Web程序,Bottle的功能略显不足,程序员需要手动管理模块、数据库、配置等等。
而如果你只是想快速创建一个Restful API接口,或者只想用网络开发框架的做一个简单的应用,Bottle可以轻松地满足你的要求。它具备了你将需要的所有功能:路由、模板、访问请求与响应数据、支持多种网络服务器以及WebSockets等高级功能。
关于安装
前面说到它小巧,它的小巧从安装就能看出来。(在虚拟环境下)
首先你可以选择安装它:
1 | $ pip install bottle==0.12.8 |
你也可以不安装它,直接下载bottle.py文件复制到自己的应用中就可以使用了。
$ wget http://bottlepy.org/bottle.py
项目构建
好像没有构建项目的必要,但如果你非要构建的话,这里有一个第三方开发的插件bottle-boilerplate可用来自动构建项目(这个插件star也不多..)。
首先来安装它:
$ pip install bottle-boilerplate
然后就可以构建项目了:
1 | bottle startproject YOUR_PROJECT_NAME |
然后就可以看到这个项目结构是这样的(这里我创建了bottle文件夹来放我的项目,我的项目名为bottleapp):
1 | |- bottle |
你已经可以运行它试一下,但这时候只能看到一个404的错误页面:
$ python -m bottle bottleapp
讲真似乎真的没有构建项目的必要..
视图函数和路由
Bottle内置了一个强大的route引擎,可以给每个浏览器请求找到正确的回调函数。
先来看一个小小的Hello World:
1 | from bottle import route,run |
在浏览器请求一个URL时,框架自动调用与之相应的函数,将函数的返回值发送给浏览器。这里route()函数将“/hello”这个URL地址绑定到“hello()”这个函数上,任何对“/hello”这个URL的请求都被递交到这个函数中。
run()启动了内置的开发服务器,把指定的域名和端口作为参数传入。它监听localhost的8080端口并响应请求.但它不能满足生产环境的需求。
Bottle的这种URL地址映射方法其实与flask差不多,也是使用了装饰器将函数和URL进行绑定的方法。
上面的route()函数将一个URL路径与一个回调函数关联起来,然后在默认应用中添加了一个URL映射(route).你也可以在你的应用中多添加几个路由器。因为一个回调函数可绑定多个route。
1 | @route('/') |
如果有一个URL没有被绑定到任何回调函数上,Bottle将返回“404 Page Not Found”的错误页面。
上面的栗子使用了模块层面的route()装饰器函数来定义route,这样,所有route都会添加到一个全局的”默认应用”,它是一个Bottle的实例,第一次调用route()时候会自动创建。
这使其他几个模块层面的修饰器函数都与这个”默认应用”有关.为了避免使用全局范围的”默认应用”,我们可以创建一个独立的应用对象.**
1 | from bottle import Bottle,run |
这样别人就可以安全地导入你的app,然后通过Bottle.mount()方法合并到他的应用中。
调试模式:
bottle.debug(True)
自动重载:
1 | from bottle import run |
动态路由:
动态路由就是有通配符的路由,它能匹配多个URL地址.URL中的通配符会当作参数传给回调函数,直接在回调函数中使用.在同一个route里面,这个变量名需要是唯一的。
1 | @route('/hello/<name>') #旧语法中为:name |
过滤器:
过滤器(Filter)可被用来定义特殊类型的通配符。在通配符传递给回调函数前,先自动转换通配符类型.包含过滤器的通配符定义一般像这样
:int 匹配一个整形,自动将其转换为int类型.
:float 匹配一个浮点数,自动将其转换为float
:path 匹配所有字符,包含”/“
:re[:config] 允许在config中写一个正则表达式.
HTTP请求方法
在Bottle中,未指明请求访问的路由会默认使用GET方法.要处理如POST,PUT或者DELETE等等的其它请求,必须主动地在route()函数中添加它们,或者使用装饰器:@get(),@post()等等.
举一个用POST方法实现用户登录的栗子:
1 | from bottle import get, post, request |
在这个栗子中,/login绑定了两个回调函数,一个回调函数响应GET请求,另一个响应POST请求。若浏览器用GET请求访问/login,则调用login_form()来返回登录界面,浏览器用POST方法提交表单后,调用login_submit()函数来检查用户有效性,并返回登录结果。
静态文件
Bottle内置的服务器不会自动处理像图片或CSS文件的静态文件请求。你需要给静态文件提供一个路由(告诉服务器哪些文件需要服务),一个回调函数(用来查找和控制静态文件的访问。)
1 | from bottle import static_file |
static_file()函数用来返回静态文件请求,上面的示例中,我们只返回”/path/to/your/static/files”路径下的文件,如果我们想要响应“/path/to/your/static/files”目录的子目录下的文件请求,那么我们可以使用一个格式化的通配符:
1 | @route('/static/<filepath:path>') |
使用root=’./static/files’这样的相对路径时,注意当前工作目录(./)不一定是项目文件夹。
错误页面
如果任何请求的URL没有的到匹配的回调函数,Bottle会返回一个默认的错误页面,提供足够的debug信息。你也可以用error()设置自己的相关回调函数,自定义错误页面:
1 | from bottle import error |
这里传给error404函数的唯一参数是一个HTTPError对象的实例。除此,这个回调函数与我们用来响应普通请求的回调函数没有不同。你可以从request中读取数据,往response中写入数据和返回所有HTTPError支持的数据类型。
只有在你的应用返回或raise一个HTTPError异常的时候,处理Error的函数才会被调用。更改Request,status或返回HTTPResponse不会触发错误处理函数。
前端模板
Bottle内置了一个快速且强大的模板引擎,SimpleTemplateEngine(stpl)。你可以使用template()函数或者view()装饰器来渲染一个模板,(这两个函数默认调用的模板引擎就是SimpleTemplate)你只要提供模板的名字和传递给模板的变量,下面是一个简单的栗子:
1 | @route('/hello') |
这将加载hello_template.tpl模板文件,并提供name变量,并渲染它,再将结果返回给浏览器。默认情况,Bottle会在./views/查找模板文件。你可以在bottle.TEMPLATE_PATH这个列表中添加模板路径。
view()装饰器允许你在回调函数中返回一个字典,并将其传递给模板。来一个栗子:
1 | @route('/hello') |
SimpleTemplate的语法
python对空白敏感的语法使它很难作为一个模板语言。SimpleTemplate移除了一些限制。SimpleTemplate模板会被编译为python字节码,且在每次通过SimpleTemplate.render()渲染时执行。
注意:编译模板和渲染模板是两件事。通常模板只会被编译一次,然后会被缓存起来,但是会根据不同的参数,被多次渲染。
内嵌语句
只要在括号中的python语句返回一个字符串或有一个字符串的表达形式,它就是一个有效的语句。
1 | 'Hello {{name}}!', name='World') template( |
括号中的python语句会在渲染的时候被执行,可访问传递给SimpleTemplate.render()方法的所有参数。默认情况下,它会自动转义HTML标签以防止XSS攻击。可在语句前加上“!”来关闭自动转义。
1 | >>>template('Hello {{name}}!', name='<b>World</b>') |
嵌入python代码
这个模板的语法类似于python的语法,它会确保语句块的正确缩进,所以你在写模板时不用担心缩进问题。
1 | name == 'World': |
一行以%开头,表明这一行是python代码。它和真正的python代码唯一的区别,在于你需要显式地在末尾添加%end语句,表明一个代码块结束。这样你就不必担心python代码中的缩进问题,SimpleTemplate模板引擎帮你处理了。不以%开头的行被当作普通文本来渲染。
只有在行首的%字符才有意义,可以使用%%来转义。
注意:模板在经过编译后会缓存在内存中,所以你在修改模板文件后,要调用bottle.TEMPLATES.clear()函数手工清除缓存,才能看到效果。而在debug模式下,缓存会被禁用,于是就无需手动清除缓存。
防止换行
在一行代码前面加上\来防止换行。
1 | <span>\\ |
该模板会输出:
<span>nobreak</span>
模板继承
- %include语句
可使用%include sub——template[kwargs]语句来包含其他模板。sub_template参数是模板的文件名或路径。[kwargs]部分是以逗号分开的键值对,是传给其他模板的参数。
1 | %include header_template title='Hello World!' |
- %rebase语句
%rebase base_template [kwargs]语句会渲染base_template这个模板,而不是原先的模板。然后base_template中使用一个空%include语句来包含原先的模板,并可访问所有通过kwargs传过来的参数。这样就可用模板来封装另一个模板,或是模拟引擎中的继承机制。**
假设现在有一个与内容有关的模板,想在它上面加一层普通的HTML层。为了避免include一堆模板,可以用一个基础模板。
名为layout.tpl的基础模板
1 | <html> |
名为 content.tpl的主模板
1 | This is the page content:{{content}} |
然后来渲染content.tpl
1 | >>> print template('content', content='Hello World!') |
模板内置函数
在模板中访问一个未定义的变量会导致NameError异常,并立即终止模板的渲染。在抛出异常前,你无法检查变量是否被定义。当你想让输入更灵活或想在不同情况下使用同一个模板时,就很烦人了。SimpleTemplate模板引擎内置了三个函数来解决这个问题。
defined(name):如果变量已定义则返回True,反之返回False
get(name,default=None):返回该变量,或一个默认值
setdefault(name,default):如果该变量未定义,则定义它,赋一个默认值,返回该变量
下面这个栗子使用了这些函数,实现了模板中的可选参数:
1 | % setdefault('text','No Text') |
数据库
Bottle没有orm,没有专门封装数据库操作,不能直接支持数据库,需要通过一些插件实现。
如果你确实想在你的应用里使用数据库,寻求ORM支持,你可以选择使用SQLAlchemy,PyMongo,MongoEngine, CouchDB等。
所以如果你需要开发基于数据库的网站,且数据库的结构不会经常变化,那最好使用大型Python Web框架。而如果你的网站使用的是关系数据库,就可以不使用大型框架,直接用bottle、flask这类框架结合关系数据库模块就行。
Key/Value数据库
Bottle通过bottle.db模块变量提供一个key/value数据库.存储的对象类似dict字典,keys和values必须是字符串.不支持items(),values()这些方法.
bottle-mysql
$ pip install bottle-mysql
“Bottle-MySQL is a plugin that integrates MySQL with your Bottle application. It automatically connects to a database at the beginning of a request, passes the database handle to the route callback and closes the connection afterwards.”
“Bottle-MySQL是一个能够将你的应用和MySQL整合起来的插件。它在请求开始的时自动地连接上数据库,通过数据库句柄到路由回调,最后关闭连接。”
1 | import bottle |
你也可以直接用python的数据库模块MYSQLdb来连接MYSQL,直接import MYSQLdb就可以。
Bottle-SQLite
这个插件让在Bottle应用中使用sqlite数据库变得简单。你只要在route的回调函数里添加一个‘db’参数,就能使用数据库链接了。
$ pip install bottle-sqlite
API编写与参考
也是跟flask差不多,不同的是它可以把HTTP请求方法作装饰器用.
一个简单的栗子:
1 | from bottle import request, response |
也可以单独创建一个API文档,将上面这段代码保存为names.py,然后再建立一个main.py文件。
1 | import bottle |
项目部署
Bottle默认运行在它内置的随python一起发布的WSGI reference Server服务器上。这个单线程的HTTP服务器在开发时很有用,但是性能较低.
最简单的增加性能的办法是安装一个多线程的服务器库,例如paste或者cherrypy ,并告诉 Bottle 使用它来替代单线程的服务器:
bottle.run(server='paste')
默认地,Bottle会监听127.0.1的8080端口,如果想更改它,就更改run函数的参数。当Bottle运行在其他服务器上时,port和host参数依然适用。
run(port=80,host='123.45.67.89')
因为这个服务器是单线程的,一次只能响应一个请求,可是Bottle已经可以工作在很多多线程的服务器上了,所以还是建议在大型项目上使用高性能服务器。
1 | Bottle v0 server starting (using WSGIRefServer())... |
其他特性(待加入)
Session
Bottle自身没有提供Session(处理用户在多次请求之间需要存储的数据)的支持,但可以使用beaker中间件来实现。
Beaker是一个缓存和会话的库,与Web应用程序和独立的Python脚本及应用程序一起使用。它是WSGI的中间件,能够很简单地嵌入,与基于WSGI的Web应用程序一起使用,并且缓存修饰器对于任何基于Python的应用程序都是容易使用的。
$ pip install beaker
栗子:
1 | from bottle import route, run ,redirect,request,default_app |
一些推荐的可用的插件
Bottle-Beaker:Beaker to session and caching library with WSGI Middleware
Bottle-Cork:Cork provides a simple set of methods to implement Authentication and Authorization in web applications based on Bottle.
Bottle-Extras:Meta package to install the bottle plugin collection.
Bottle-Flash:flash plugin for bottle
Bottle-Hotqueue:FIFO Queue for Bottle built upon redis
Macaron:Macaron is an object-relational mapper (ORM) for SQLite.
Bottle-Memcache:Memcache integration for Bottle.
Bottle-Mongo:MongoDB integration for Bottle
Bottle-Redis:Redis integration for Bottle.
Bottle-Renderer:Renderer plugin for bottle
Bottle-ServefilesA reusable app that serves static files for bottle apps
Bottle-Sqlalchemy:SQLAlchemy integration for Bottle.
Bottle-Sqlite:SQLite3 database integration for Bottle.
Bottle-Web2pydal:Web2py Dal integration for Bottle.
Bottle-Werkzeug:Integrates the werkzeug library (alternative request and response objects, advanced debugging middleware and more)
Bottle学习资源
- PS:因为Bottle真的太小了,以至于网上关于它的资料也比较少,而且基本上都是差不多的,感觉官方文档也不是很全面,相关的书也没有,于是只能大量百度和google来搜集资料学习。
Bottle: Python Web Framework
Bottle v0.11中文文档
简单介绍Python的轻便web框架Bottle
bottle框架基础教程
Bottle web 开发 (视频)
几个bottle插件
bottle-mysql 0.1.4
Python Web框架
Bottle手册(0.13-dev)中文翻译
bottle 源码解析
初窥Bottle
Python程序员都会喜欢的6个库
bottle中文
微型Python Web框架 Bottl
bottle中文教程
Python的Bottle框架的一些使用技巧介绍
Bottle框架常见的几个坑
Bottle API 参考 中文
Where to start a project with bottle, Boilerplate
Python3 bottle Web开发系列教程
Building a Rest API with the Bottle Framework
Developing With Bottle
Bottle API 参考