🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
{% raw %} # Bottle 教程 > 原文: [http://zetcode.com/python/bottle/](http://zetcode.com/python/bottle/) Bottle 教程展示了如何使用 Python Bottle Web 微框架在 Python 中创建简单的 Web 应用。 ## Bottle Bottle 是用于 Python 的快速,简单且轻量级的 WSGI 微型网络框架。 它作为单个文件模块分发。 除 Python 标准库外,没有其他依赖项。 Web 服务器网关接口(WSGI)是 Web 服务器的简单调用约定,用于将请求转发到以 Python 编程语言编写的 Web 应用或框架。 ## Bottle 安装 ```py $ sudo pip3 install bottle ``` 我们使用`pip3`工具安装 Bottle。 ## Bottle 简单的例子 在下面的示例中,我们创建一个简单的 Bottle 应用。 ```py $ mkdir simple && cd simple $ touch simple.py ``` 我们创建一个项目目录一个 Python 文件。 `simple.py` ```py #!/usr/bin/env python3 from bottle import route, run @route('/message') def hello(): return "Today is a beautiful day" run(host='localhost', port=8080, debug=True) ``` 该示例向客户端发送一条消息。 ```py from bottle import route, run ``` 我们导入`route`装饰器和`run`函数。 `route`装饰器用于将函数绑定到请求 URL。 `run`函数启动服务器实例。 默认情况下,它是开发服务器。 ```py @route('/message') def hello(): return "Today is a beautiful day" ``` 使用`@route()`装饰器,我们定义了一个路由。 路由是 URL 与 Web 服务器函数之间的映射。 在我们的例子中,该函数返回一条简单的文本消息。 ```py run(host='localhost', port=8080, debug=True) ``` 我们以调试模式在端口 8080 上启动服务器。 ```py $ ./simple.py Bottle v0.12.13 server starting up (using WSGIRefServer())... Listening on http://localhost:8080/ Hit Ctrl-C to quit. ``` 我们启动开发服务器。 ```py $ curl localhost:8080/message Today is a beautiful day ``` 我们使用`curl`工具创建一个请求。 服务器以一条简单消息响应。 ## Bottle JSON 响应 Web 应用通常以 JSON 格式发送响应。 Bottle 自动将 Python 字典转换为 JSON。 `json_response.py` ```py #!/usr/bin/env python3 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 发送到客户端。 ```py return dict(data=cars) ``` Bottle 将 Python 字典转换为 JSON。 ```py $ 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 获取请求 HTTP GET 方法请求指定资源的表示形式。 在 Bottle 中,我们可以使用`@route`或`@get`装饰器映射 GET 请求。 从`request.query`检索数据。 GET 请求通常是默认的请求方法。 `get_request.py` ```py #!/usr/bin/env python3 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 请求的数据构建一条消息。 ```py @get('/msg') def message(): ``` `message()`函数通过`/msg`路径映射到 GET 请求。 `@get('msg')`装饰器等效于`@route('msg', method='GET')`,或更短的`@route('msg')`。 ```py name = request.query.name age = request.query.age ``` 我们从查询字符串中检索数据。 ```py $ curl "localhost:8080/greet?name=Peter&age=34" Peter is 34 years old ``` 我们使用`curl`工具发出 GET 请求。 GET 请求是`curl`的默认请求。 我们将`name`和`age`参数添加到查询字符串。 ## Bottle 静态文件 使用`static_file()`,我们可以在 Bottle 中提供静态文件。 ```py $ mkdir botstat && cd botstat $ mkdir public $ touch public/home.html app.py ``` 我们为应用创建目录和文件。 `public/home.html` ```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`。 `app.py` ```py #!/usr/bin/env python3 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`。 ```py @route('/<filepath:path>') ``` `filepath:path`是仅允许出现在包含斜杠的路径中的字符的过滤器。 ```py return static_file(filepath, root='./public/') ``` 通过`static_file()`函数,我们可以提供静态文件。 静态文件所在的目录在`root`参数中指定。 ## Bottle 过滤器 包含通配符的路由称为动态路由(与静态路由相对)。 它们可以同时匹配多个 URL。 通配符由括在尖括号中的名称组成(例如`<name>`),并且可以接受一个或多个字符,直到下一个斜杠为止。 过滤器可用于定义更特定的通配符。 * `:int`匹配(带符号)数字 * `:float`匹配十进制数字 * `:path`路径段中允许使用的数学字符 * `:re`允许指定自定义正则表达式 `filters.py` ```py #!/usr/bin/env python3 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) ``` 该示例使用整数过滤器和正则表达式过滤器。 ```py $ curl localhost:8080/app/3/ Object with id 3 returned ``` 在这里,我们向路径添加一个整数。 ## Bottle 例子 在下面的示例中,我们将表单发送到 Bottle 应用。 ```py $ mkdir simple_form && cd simple_form $ mkdir public $ touch public/index.html simple_form.py ``` 我们为应用创建目录和文件。 `public/index.html` ```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 文件中,我们有一个表单标签。 该表格包含两个输入字段:名称和职业。 `simple_form.py` ```py #!/usr/bin/env python3 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`文件中,我们提供一个表格并处理该表格。 ```py @route('/') def server_static(filepath="index.html"): return static_file(filepath, root='./public/') ``` 对于根路径(/),我们从`public`目录提供`index.html`。 ```py @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`装饰器创建自定义错误页面。 `error_handler.py` ```py #!/usr/bin/env python3 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 错误。 ```py @error(404) def error404(error): return '404 - the requested page could not be found' ``` `@error`装饰器将错误代码作为参数。 ```py $ curl localhost:8080/app/Peter 404 - the requested page could not be found ``` 我们尝试访问未定义的路由; 我们会收到自定义错误消息。 ## Bottle MongoDB 示例 在以下示例中,我们从 MongoDB 数据库以 JSON 形式返回数据。 `create_cars.py` ```py #!/usr/bin/python3 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 教程](/python/pymongo/)。 `bottle_mongo.py` ```py #!/usr/bin/env python3 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) ``` 该示例从 Mongo 集合返回数据作为 JSON。 ```py client = MongoClient('mongodb://localhost:27017/') ``` 创建一个`MongoClient`实例。 ```py db = client.testdb cars = list(db.cars.find({}, {'_id': 0})) ``` 我们从两个字段中检索所有数据; 我们排除`_id`字段。 ```py if cars: return json.dumps(cars) else: raise HTTPResponse(status=204) ``` 如果有数据,我们将使用`json.dumps()`将其转换为 JSON,然后将其返回给客户端。 否则,我们会发送 204 状态代码。 ## Bottle 模板示例 模板引擎是一个旨在将模板与数据模型结合以生成结果文档的库。 默认情况下,Bottle 使用简单的模板引擎。 ```py $ mkdir botview && cd botview $ mkdir views $ touch views/show_cars.tpl app.py ``` 我们为应用创建目录和文件。 `views/show_cars.tpl` ```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`目录中。 `app.py` ```py #!/usr/bin/env python3 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 应用。 您可能也对以下相关教程感兴趣: [PyMongo 教程](/python/pymongo/), [Jinja 教程](/python/jinja/)和 [Python 教程](/lang/python/)。 {% endraw %}