Bottle
最后修改于 2024 年 1 月 29 日
Bottle 教程演示了如何使用 Python Bottle 微型 Web 框架在 Python 中创建简单的 Web 应用。
Bottle
Bottle 是一个快速、简单、轻量级的 Python WSGI 微型 Web 框架。它以单个文件模块的形式分发。除了 Python 标准库之外,没有任何依赖项。
Web 服务器网关接口 (WSGI) 是一个简单的调用约定,用于 Web 服务器将请求转发给用 Python 编程语言编写的 Web 应用或框架。
Bottle 安装
$ sudo pip3 install bottle
我们使用 pip3
工具来安装 Bottle。
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 和 Web 服务器功能之间的映射。在我们的例子中,该功能返回一个简单的文本消息。
run(host='localhost', port=8080, debug=True)
我们在调试模式下将服务器运行在 8080 端口。
$ ./simple.py Bottle v0.12.13 server starting up (using WSGIRefServer())... Listening on https://:8080/ Hit Ctrl-C to quit.
我们启动一个开发服务器。
$ curl localhost:8080/message Today is a beautiful day
我们使用 curl
工具创建请求。服务器以简单消息进行响应。
Bottle 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 数组。
Bottle GET 请求
HTTP GET 方法请求指定资源的表示。在 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 请求。GET 请求是 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
参数中指定。
Bottle 过滤器
包含通配符的路由称为动态路由(与静态路由相对)。它们可以同时匹配多个 URL。通配符由一对尖括号括起来的名称组成(例如 <name>),它可以匹配一个或多个字符,直到下一个斜杠。
过滤器可用于定义更具体的通配符。
- :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 表单示例
在下面的示例中,我们将一个表单发送到 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 文件中,我们有一个 form 标签。该表单包含两个输入字段:name 和 occupation。
#!/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
获取数据并构建消息字符串。
Bottle 错误处理程序
可以使用 @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
我们尝试访问一个未定义的路由;我们会收到自定义错误消息。
Bottle MongoDB 示例
在下面的示例中,我们从 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://: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://: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://: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 模板示例
模板引擎是一种旨在将模板与数据模型结合以生成结果文档的库。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://: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 教程。