Bottle教程展示了如何使用PythonBottle微型Web框架在Python中创建简单的Web应用程序。
瓶子
Bottle是一种用于Python的快速、简单且轻量级的WSGI微型网络框架。它作为单个文件模块分发。除了Python标准库之外,没有其他依赖项。
Web服务器网关接口(WSGI)是Web服务器将请求转发到使用Python编程语言编写的Web应用程序或框架的简单调用约定。
瓶子安装
$ sudo pip3 install bottle
我们使用pip3
工具来安装Bottle。
瓶子简单例子
在下面的示例中,我们创建了一个简单的Bottle应用程序。
$ mkdir simple && cd simple $ touch simple.py
我们创建一个项目目录和一个Python文件。
#!/usr/bin/python from bottle import route, run @route('/message') def hello(): return "Today is a beautiful day" run(host='localhost', port=8080, debug=True)
该示例向客户端发送消息。
from bottle import route, run
我们导入了route
装饰器和run
函数。route
装饰器用于将函数绑定到请求URL。run
函数启动一个服务器实例。默认情况下,它是一个开发服务器。
@route('/message') def hello(): return "Today is a beautiful day"
使用@route
装饰器,我们定义了一条路线。路由是URL和网络服务器功能之间的映射。在我们的例子中,该功能返回一条简单的文本消息。
run(host='localhost', port=8080, debug=True)
我们以调试模式在端口8080上启动服务器。
$ ./simple.py Bottle v0.12.13 server starting up (using WSGIRefServer())... Listening on http://localhost:8080/ Hit Ctrl-C to quit.
我们启动一个开发服务器。
$ curl localhost:8080/message Today is a beautiful day
我们使用curl
工具创建一个请求。服务器以简单的消息响应。
瓶子JSON响应
Web应用程序通常以JSON格式发送响应。Bottle自动将Python字典转换为JSON。
#!/usr/bin/python from bottle import route, run @route('/cars') def getcars(): cars = [ {'name': 'Audi', 'price': 52642}, {'name': 'Mercedes', 'price': 57127}, {'name': 'Skoda', 'price': 9000}, {'name': 'Volvo', 'price': 29000}, {'name': 'Bentley', 'price': 350000}, {'name': 'Citroen', 'price': 21000}, {'name': 'Hummer', 'price': 41400}, {'name': 'Volkswagen', 'price': 21600} ] return dict(data=cars) run(host='localhost', port=8080, debug=True)
应用程序将有关汽车的数据作为JSON发送给客户端。
return dict(data=cars)
Bottle将Python字典转换为JSON。
$ curl localhost:8080/cars {"data": [{"name": "Audi", "price": 52642}, {"name": "Mercedes", "price": 57127}, {"name": "Skoda", "price": 9000}, {"name": "Volvo", "price": 29000}, {"name": "Bentley", "price": 350000}, {"name": "Citroen", "price": 21000}, {"name": "Hummer", "price": 41400}, {"name": "Volkswagen", "price": 21600}]}
我们收到一个命名的JSON数组。
瓶子GET请求
HTTPGET方法请求指定资源的表示。在Bottle中,我们可以使用@route
或@get
装饰器映射GET请求。从request.query
中检索数据。
GET请求通常是默认的请求方式。
#!/usr/bin/python from bottle import route, run, request, get @get('/msg') def message(): name = request.query.name age = request.query.age return "{0} is {1} years old".format(name, age) run(host='localhost', port=8080, debug=True)
应用程序根据GET请求的数据构建消息。
@get('/msg') def message():
message
函数映射到路径为/msg
的GET请求。@get('msg')
装饰器等同于@route('msg',method='GET')
,或者更短的@route('msg')。
name = request.query.name age = request.query.age
我们从查询字符串中检索数据。
$ curl "localhost:8080/greet?name=Peter&age=34" Peter is 34 years old
我们使用curl
工具发出GET请求。GETrequest是curl
的默认值。我们将name
和age
参数添加到查询字符串中。
Bottle服务静态文件
使用static_file
,我们可以在Bottle中提供静态文件。
$ mkdir botstat && cd botstat $ mkdir public $ touch public/home.html app.py
我们为应用程序创建目录和文件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Home page</title> </head> <body> <p>This is home page</p> </body> </html>
这是位于public
目录中的主页。静态资源目录通常称为public
或static
。
#!/usr/bin/python from bottle import route, run, static_file @route('/<filepath:path>') def server_static(filepath): return static_file(filepath, root='./public/') run(host='localhost', port=8080, debug=True)
我们在这个例子中提供静态文件。为了获得主页,我们必须导航到localhost:8080/home.html
。
@route('/<filepath:path>')
filepath:path
是一个过滤器,它只允许出现在路径中的字符,包括斜杠。
return static_file(filepath, root='./public/')
使用static_file
函数,我们提供静态文件。静态文件所在的目录在root
参数中指定。
瓶式过滤器
包含通配符的路由称为动态路由(相对于静态路由)。它们可以同时匹配多个URL。通配符由括在尖括号中的名称组成(例如),并接受一个或多个字符直至下一个斜杠。
过滤器可用于定义更具体的通配符。
- :int匹配(有符号)数字
- :float匹配十进制数
- :path允许在路径段中使用数学字符
- :re允许指定自定义正则表达式
#!/usr/bin/python from bottle import route, run @route('/app/<myid:int>/') def provide(myid): return "Object with id {} returned".format(myid) @route('/app/<name:re:[a-z]+>/') def provide(name): return "Name {} given".format(name) run(host='localhost', port=8080, debug=True)
该示例使用整数过滤器和正则表达式过滤器。
$ curl localhost:8080/app/3/ Object with id 3 returned
这里我们向路径添加一个整数。
瓶形示例
在下面的示例中,我们将表单发送到Bottle应用程序。
$ mkdir simple_form && cd simple_form $ mkdir public $ touch public/index.html simple_form.py
我们为应用程序创建目录和文件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Home page</title> </head> <body> <form method="post" action="doform"> <div> <label for="name">Name:</label> <input type="text" id="name" name="name"> </div> <div> <label for="occupation">Occupation:</label> <input type="text" id="occupation" name="occupation"> </div> <button type="submit">Submit</button> </form> </body> </html>
在HTML文件中,我们有一个表单标签。该表单包含两个输入字段:姓名和职业。
#!/usr/bin/python from bottle import route, run, post, request, static_file @route('/') def server_static(filepath="index.html"): return static_file(filepath, root='./public/') @post('/doform') def process(): name = request.forms.get('name') occupation = request.forms.get('occupation') return "Your name is {0} and you are a(n) {1}".format(name, occupation) run(host='localhost', reloader=True, port=8080, debug=True)
在simple_form.py
文件中,我们提供一个表单并处理该表单。
@route('/') def server_static(filepath="index.html"): return static_file(filepath, root='./public/')
对于根路径(/),我们从public
目录提供index.html
。
@post('/doform') def process(): name = request.forms.get('name') occupation = request.forms.get('occupation') return "Your name is {0} and you are a(n) {1}".format(name, occupation)
这里我们处理表单。我们使用@post
装饰器。我们从request.forms
获取数据并构建消息字符串。
瓶子错误处理器
可以使用@error
装饰器创建自定义错误页面。
#!/usr/bin/python from bottle import route, run, error @route('/app/<myid:int>') def provide(myid): return "Object with id {} returned".format(myid) @error(404) def error404(error): return '404 - the requested page could not be found' run(host='localhost', port=8080, debug=True)
在此示例中,我们在自定义错误处理程序中处理404错误。
@error(404) def error404(error): return '404 - the requested page could not be found'
@error
装饰器将错误代码作为参数。
$ curl localhost:8080/app/Peter 404 - the requested page could not be found
我们尝试访问一个没有定义的路由;我们收到自定义错误消息。
BottleMongoDB示例
在下面的示例中,我们从MongoDB数据库返回JSON格式的数据。
#!/usr/bin/python from pymongo import MongoClient cars = [ {'name': 'Audi', 'price': 52642}, {'name': 'Mercedes', 'price': 57127}, {'name': 'Skoda', 'price': 9000}, {'name': 'Volvo', 'price': 29000}, {'name': 'Bentley', 'price': 350000}, {'name': 'Citroen', 'price': 21000}, {'name': 'Hummer', 'price': 41400}, {'name': 'Volkswagen', 'price': 21600} ] client = MongoClient('mongodb://localhost:27017/') with client: db = client.testdb db.cars.insert_many(cars)
使用此脚本,我们创建了一个Mongo集合。有关在Python中使用MongoDB的更多信息,请参阅PyMongo教程。
#!/usr/bin/python from bottle import route, run, HTTPResponse from pymongo import MongoClient import json client = MongoClient('mongodb://localhost:27017/') @route('/cars') def getcars(): db = client.testdb cars = list(db.cars.find({}, {'_id': 0})) if cars: return json.dumps(cars) else: raise HTTPResponse(status=204) run(host='localhost', port=8080, debug=True)
该示例以JSON格式从Mongo集合返回数据。
client = MongoClient('mongodb://localhost:27017/')
创建了一个MongoClient
实例。
db = client.testdb cars = list(db.cars.find({}, {'_id': 0}))
我们从两个字段中检索所有数据;我们排除了_id
字段。
if cars: return json.dumps(cars) else: raise HTTPResponse(status=204)
如果有数据,我们使用json.dumps
将它们转换为JSON,并将它们返回给客户端。否则,我们发送204状态码。
瓶子模板示例
模板引擎是一个库,旨在将模板与数据模型结合起来以生成结果文档。Bottle默认使用简单的模板引擎。
$ mkdir botview && cd botview $ mkdir views $ touch views/show_cars.tpl app.py
我们为应用程序创建目录和文件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Cars</title> </head> <body> <table> <tr> <th>Name</th> <th>Price</th> </tr> % for car in cars: <tr> <td>{{car['name']}}</td> <td>{{car['price']}}</td> </tr> % end </table> </body> </html>
在这个模板中,我们遍历接收到的cars
对象并从中生成一个表。模板文件位于views
目录中。
#!/usr/bin/python from bottle import route, run, template, HTTPResponse from pymongo import MongoClient client = MongoClient('mongodb://localhost:27017/') @route('/cars') def getcars(): db = client.testdb data = db.cars.find({}, {'_id': 0}) if data: return template('show_cars', cars=data) else: return HTTPResponse(status=204) run(host='localhost', port=8080, debug=True)
在应用程序中,我们从MongoDB集合中检索数据。我们使用template
函数将模板文件与数据组合。
在本教程中,我们使用Bottle在Python中创建了简单的Web应用程序。
阅读Python教程或列出所有Python教程。