【Python】Bottle:轻量Web框架

Bottle快速开始

Bottle 是一个非常轻量级的 Python Web 框架,适合用于构建简单的 Web 应用和 RESTful API。Bottle 的最大特点之一是它的单文件设计,意味着你只需下载一个文件 bottle.py 即可使用整个框架,而不需要安装其他依赖。在这篇教程中,我们将演示如何通过下载 bottle.py 文件并直接导入它,快速搭建你的第一个 Web 应用。

环境搭建:通过单个 bottle.py 文件

获取 Bottle 库
  1. 下载 bottle.py 文件

    Bottle 的源代码可以直接从GitHub 仓库下载,或者通过以下步骤手动获取:

    • 打开浏览器,访问 https://github.com/bottlepy/bottle。
    • 点击 “Code” 按钮,然后选择 “Download ZIP” 下载整个仓库。
    • 解压后,找到 bottle.py 文件。
  2. bottle.py 文件放置在项目目录

    将下载的 bottle.py 文件复制到你项目的根目录下。这就是你整个框架的全部内容,无需安装其他包或依赖。

创建一个简单的 bottle.py 文件

在项目的根目录下,创建一个新的 Python 文件,比如 app.py,用来编写 Web 应用代码。你不需要通过 import bottle 来加载整个框架,而是直接导入 bottle.py 文件。可以通过如下方式实现:

# 导入本地的 bottle.py 文件
from bottle import route, run# 定义路由及处理函数
@route('/hello')
def hello():return "Hello, World!"# 启动应用
run(host='localhost', port=8080)

在这里,我们直接使用了 bottle.py 文件提供的 routerun 函数。这个 bottle.py 文件会被自动识别,并且框架本身也能完美工作。

第一个 Bottle 应用

现在我们已经完成了环境搭建,接下来我们将通过编写简单的路由和请求处理函数,创建一个基本的 Bottle Web 应用。

创建一个最简单的 Web 应用

编辑 app.py 文件,并写入以下代码:

from bottle import route, run# 创建一个简单的路由
@route('/hello')
def hello():return "Hello, World!"# 启动应用
run(host='localhost', port=8080)
代码解析
  • from bottle import route, run:这行代码导入了 routerun 函数,它们分别用于定义路由和启动应用。
  • @route('/hello'):这是一个路由装饰器,告诉 Bottle 当访问 /hello 路径时,执行下面的 hello() 函数。
  • def hello()::这是定义的视图函数。当用户访问 /hello 时,返回一个简单的文本响应:“Hello, World!”。
  • run(host='localhost', port=8080):启动应用,监听本地 localhost 地址的 8080 端口。
运行应用
  1. 打开终端,进入到 app.py 所在的目录。

  2. 直接运行 app.py 文件:

    python app.py
    
  3. 打开浏览器,访问 http://localhost:8080/hello,你应该能够看到显示 “Hello, World!” 的页面。

路由和请求方法

在 Bottle 中,路由是 Web 应用的核心,决定了不同 URL 请求应该由哪个函数来处理。你可以通过 route() 函数为不同的 URL 配置不同的请求处理函数,支持多种 HTTP 请求方法。

路由参数

Bottle 允许你在路由中定义参数,这样 URL 路径中的一部分就可以作为参数传递给视图函数。

@route('/greet/<name>')
def greet(name):return f'Hello {name}!'

当你访问 http://localhost:8080/greet/John 时,URL 中的 John 会被捕获并传递给 greet() 函数中的 name 参数,返回 “Hello John!”。

请求方法

Bottle 支持不同的 HTTP 请求方法,如 GET、POST、PUT 和 DELETE。你可以在路由定义中明确指定请求方法。

GET 请求

GET 请求通常用于获取数据,它是 Web 应用中最常见的请求方法。

@route('/hello', method='GET')
def hello():return "This is a GET request!"

访问 http://localhost:8080/hello 时,将返回 “This is a GET request!”。

POST 请求

POST 请求通常用于提交数据,比如提交表单。

from bottle import request@route('/submit', method='POST')
def submit():name = request.forms.get('name')return f'Hello {name}, your form has been submitted!'

你可以通过 HTML 表单将数据发送到 /submit 路由,当表单提交时,返回 “Hello {name}, your form has been submitted!”。

PUT 和 DELETE 请求

PUT 和 DELETE 请求通常用于更新或删除资源。你可以通过 method='PUT'method='DELETE' 显式指定这些方法。

@route('/update/<name>', method='PUT')
def update(name):return f'User {name} has been updated!'@route('/delete/<name>', method='DELETE')
def delete(name):return f'User {name} has been deleted!'

访问 /update/John/delete/John 路径时,分别返回 “User John has been updated!” 和 “User John has been deleted!”。

请求数据:表单和 URL 参数

Bottle 提供了简单的 API 来处理请求中的数据:

  • URL 参数:通过动态路由捕获 URL 参数,或者使用 request.query 获取查询字符串中的参数。
  • 表单数据:通过 request.forms 获取 POST 请求中的表单数据。
@route('/greet')
def greet():name = request.query.name  # 获取查询字符串中的参数return f'Hello {name}!'

访问 http://localhost:8080/greet?name=John 将返回 “Hello John!”。

路由与请求处理

在构建 Web 应用时,路由与请求处理是核心概念之一。Bottle 作为一个轻量级的 Python Web 框架,其路由系统非常简洁且易于理解。它通过装饰器的方式定义路由,并为每个请求分配一个处理函数。在这篇教程中,我们将详细讲解 Bottle 中的路由参数、请求对象和响应对象的使用,帮助你深入理解 Bottle 框架的请求处理机制。

路由参数

路由参数是 Web 应用中的常见需求,它使得 URL 中的某些部分可以动态地映射到视图函数的参数。Bottle 提供了非常简单的方式来定义路由参数,使得你可以根据请求路径中的参数进行数据处理。

动态路由参数

Bottle 的路由支持动态参数,可以通过在 URL 路径中使用 <param> 占位符来捕获路径的一部分。

from bottle import route, run@route('/greet/<name>')
def greet(name):return f"Hello, {name}!"run(host='localhost', port=8080)

在这个例子中,<name> 就是一个动态路由参数,表示 URL 中的路径部分。访问 http://localhost:8080/greet/John 时,John 会作为参数传递给 greet() 函数,返回结果是 Hello, John!

参数类型:
Bottle 支持多种类型的路由参数,可以通过自定义参数类型来限制输入的内容:

  • 字符串参数:默认情况下,路由参数是字符串类型。
  • 整数参数:可以通过在路由参数中指定类型来限制只能匹配整数。
@route('/user/<id:int>')
def show_user(id):return f"User ID is {id}"

访问 http://localhost:8080/user/123 时,id 将是一个整数。如果你访问一个非整数的值(例如 /user/abc),Bottle 会自动返回 404 错误。

捕获多个参数

你可以在一个路由中捕获多个参数,只需在路由路径中使用多个占位符即可。

@route('/greet/<first_name>/<last_name>')
def greet_full_name(first_name, last_name):return f"Hello, {first_name} {last_name}!"

访问 http://localhost:8080/greet/John/Doe 时,first_namelast_name 将分别是 JohnDoe

使用正则表达式限制参数

如果你需要更精细的控制,可以通过正则表达式来限制路由参数的格式。可以在路由装饰器中使用 re 参数来指定正则表达式。

import re@route('/item/<id:re:[0-9]+>')
def show_item(id):return f"Item ID is {id}"

在这个例子中,<id:re:[0-9]+> 表示 id 参数必须是一个数字。如果访问 http://localhost:8080/item/123,返回 Item ID is 123,但访问 /item/abc 会返回 404 错误。

请求对象

在 Bottle 中,request 对象用于表示 HTTP 请求的所有信息。通过 request 对象,你可以获取请求的各种数据,包括查询参数、表单数据、HTTP 请求头、客户端信息等。

获取 URL 查询参数

查询参数是 URL 中 ? 后面的部分,通常以键值对的形式传递。例如,访问 http://localhost:8080/greet?name=Johnname=John 就是查询参数。

from bottle import request@route('/greet')
def greet():name = request.query.name  # 获取查询参数中的 'name' 参数return f"Hello, {name}!"

访问 http://localhost:8080/greet?name=John 时,name 的值将是 John,返回的内容是 Hello, John!

获取表单数据

表单数据通常通过 POST 请求提交,可以通过 request.forms 来访问表单字段的值。

@route('/submit', method='POST')
def submit():name = request.forms.get('name')  # 获取表单数据中的 'name' 字段return f"Hello, {name}, your form has been submitted!"

HTML 表单代码示例:

<form action="/submit" method="POST"><input type="text" name="name" placeholder="Enter your name" /><input type="submit" value="Submit" />
</form>
获取请求头

请求头包含关于请求的元数据,如浏览器信息、内容类型等。你可以通过 request.headers 获取请求头。

@route('/headers')
def show_headers():user_agent = request.headers.get('User-Agent')  # 获取 User-Agent 请求头return f"Your User-Agent is: {user_agent}"
获取请求方法

request.method 返回当前请求的 HTTP 方法(如 GETPOSTPUTDELETE 等)。你可以根据请求方法来决定如何处理请求。

@route('/check_method', method=['GET', 'POST'])
def check_method():if request.method == 'GET':return "This is a GET request"else:return "This is a POST request"

响应对象

在 Bottle 中,视图函数通常会返回一个字符串或者其它类型的响应,但你也可以使用 response 对象来对响应进行更细致的控制。response 对象提供了很多功能,可以让你控制响应的内容类型、HTTP 状态码等。

设置响应内容

默认情况下,Bottle 会将视图函数的返回值作为响应内容。如果你需要返回更复杂的内容(如 JSON 或者 HTML),可以直接操作 response.body

from bottle import response
import json@route('/json')
def get_json():data = {'name': 'John', 'age': 30}response.content_type = 'application/json'  # 设置响应内容类型为 JSONreturn json.dumps(data)

在这个例子中,返回的内容类型为 application/json,表示响应的数据是 JSON 格式。

设置响应头

你可以使用 response.headers 设置返回的 HTTP 响应头。

@route('/custom_header')
def custom_header():response.headers['X-Custom-Header'] = 'Hello, World!'return "Response with custom header"

访问这个路由时,返回的响应会包含一个名为 X-Custom-Header 的自定义响应头,值为 Hello, World!

设置 HTTP 状态码

通过设置 response.status,你可以控制返回的 HTTP 状态码。默认情况下,Bottle 会返回 200 状态码,表示请求成功。如果你希望返回其他状态码,可以手动设置。

@route('/error')
def error():response.status = 404  # 设置状态码为 404return "Page not found"

访问 /error 路径时,浏览器会接收到 404 错误。

构建RESTful API

RESTful API(代表性状态转移的应用程序接口)是一种设计风格,通过HTTP协议实现客户端与服务器之间的通信。在Web应用中,RESTful API非常常见,它允许客户端与服务器以标准的方式进行交互。在这篇教程中,我们将深入介绍如何使用 Bottle 框架构建RESTful API,涵盖 RESTful 设计原则、GET、POST、PUT 和 DELETE 请求的实现。

RESTful设计原则

REST(Representational State Transfer)是一种基于 Web 的架构风格,其核心设计思想是通过 HTTP 协议的方法(GET、POST、PUT、DELETE)来操作资源。以下是 RESTful API 的一些关键设计原则:

  • 资源:每个数据实体或信息对象(如用户、文章、产品)都被视为一个资源。资源应该有一个唯一的 URI(统一资源标识符)。
  • HTTP 方法
    • GET:用于获取资源。
    • POST:用于创建资源。
    • PUT:用于更新资源。
    • DELETE:用于删除资源。
  • 无状态:每个请求都应该包含足够的信息来进行处理,服务器不应保存任何客户端的状态。
  • 支持多种数据格式:API 支持多种格式(如 JSON、XML)来表示资源。
  • 统一接口:每个 API 都应该是幂等的(即无论请求多少次,结果是相同的),并且应该遵循一致的路径命名和参数设计。

创建基础应用

from bottle import Bottle, runapp = Bottle()@app.route('/')
def home():return "Welcome to the Bottle RESTful API!"run(app, host='localhost', port=8080)

运行上述代码后,访问 http://localhost:8080/ 可以看到 “Welcome to the Bottle RESTful API!” 的欢迎信息。

创建GET请求API

GET 请求用于从服务器获取资源。在 RESTful API 中,GET 请求是最常见的请求方式,通常用于获取单个资源或资源的列表。

获取单个资源

假设我们有一个简单的资源模型 User,我们可以通过 ID 来获取用户信息。

from bottle import Bottle, run, request, responseapp = Bottle()# 模拟的用户数据
users = {1: {"name": "John Doe", "email": "john@example.com"},2: {"name": "Jane Smith", "email": "jane@example.com"}
}@app.route('/users/<user_id:int>', method='GET')
def get_user(user_id):user = users.get(user_id)if user:response.content_type = 'application/json'return {"id": user_id, "name": user["name"], "email": user["email"]}else:response.status = 404return {"error": "User not found"}run(app, host='localhost', port=8080)

在这个例子中,/users/<user_id:int> 路径接收一个用户 ID 作为路径参数,返回对应的用户信息。如果用户不存在,则返回 404 错误。

访问 http://localhost:8080/users/1 会返回用户 John Doe 的信息,访问 http://localhost:8080/users/3 会返回 404 错误。

获取所有资源

我们可以扩展上面的应用,来获取所有用户的列表。

@app.route('/users', method='GET')
def get_users():response.content_type = 'application/json'return {"users": list(users.values())}

访问 http://localhost:8080/users 将返回所有用户的 JSON 列表。

创建POST请求API

POST 请求通常用于创建资源。当客户端发送一个 POST 请求时,服务器会根据请求数据创建一个新的资源,并返回该资源的信息。

创建新用户
@app.route('/users', method='POST')
def create_user():# 获取请求体中的 JSON 数据user_data = request.jsonif not user_data or not user_data.get('name') or not user_data.get('email'):response.status = 400return {"error": "Name and email are required"}# 创建一个新的用户new_id = max(users.keys()) + 1users[new_id] = {"name": user_data['name'], "email": user_data['email']}response.status = 201  # 返回 201 创建成功状态码return {"id": new_id, "name": user_data['name'], "email": user_data['email']}

在此代码中,客户端通过 POST 请求发送一个 JSON 格式的用户数据,服务器将创建一个新用户并返回新用户的 ID、名字和邮箱。返回的状态码是 201 Created,表示资源已成功创建。

通过工具(如 Postman)发送 POST 请求 http://localhost:8080/users,并附带如下 JSON 数据:

{"name": "Tom Hanks","email": "tom@example.com"
}

会创建一个新的用户并返回创建的用户数据。

创建PUT请求API

PUT 请求用于更新现有的资源。它要求客户端提供完整的资源信息,服务器将该资源替换为客户端提供的数据。

更新用户信息
@app.route('/users/<user_id:int>', method='PUT')
def update_user(user_id):user_data = request.jsonuser = users.get(user_id)if not user:response.status = 404return {"error": "User not found"}if not user_data or not user_data.get('name') or not user_data.get('email'):response.status = 400return {"error": "Name and email are required"}# 更新用户数据user['name'] = user_data['name']user['email'] = user_data['email']return {"id": user_id, "name": user['name'], "email": user['email']}

在此代码中,客户端通过 PUT 请求发送新的用户数据,服务器将根据提供的 ID 更新该用户的资料。请求体必须包含完整的用户信息(如姓名和邮箱)。

通过工具(如 Postman)发送 PUT 请求 http://localhost:8080/users/1,并附带如下 JSON 数据:

{"name": "John Doe Updated","email": "john.updated@example.com"
}

这将更新用户 ID 为 1 的信息,并返回更新后的用户数据。

创建DELETE请求API

DELETE 请求用于删除现有的资源。当客户端发送 DELETE 请求时,服务器将删除指定的资源。

删除用户
@app.route('/users/<user_id:int>', method='DELETE')
def delete_user(user_id):user = users.pop(user_id, None)if user:return {"message": "User deleted successfully"}else:response.status = 404return {"error": "User not found"}

在此代码中,客户端通过 DELETE 请求删除指定 ID 的用户。如果删除成功,返回一条成功消息;如果用户不存在,返回 404 错误。

通过工具(如 Postman)发送 DELETE 请求 http://localhost:8080/users/1,将删除用户 ID 为 1 的用户。

模板与静态文件

在构建 Web 应用时,模板渲染和静态文件服务是常见且重要的功能。模板渲染帮助你将数据与 HTML 结构分离,提供动态内容的展示;静态文件服务则让你可以轻松处理 CSS、JavaScript、图片等不需要动态生成的文件。Bottle 作为一个轻量级框架,内建了对这两种功能的支持,使得 Web 开发变得更加简洁和高效。在本教程中,我们将深入介绍如何在 Bottle 中使用模板渲染和静态文件服务。

使用模板渲染

模板引擎允许你将动态数据与静态 HTML 文件结合,生成最终的响应内容。在 Bottle 中,默认使用的是 SimpleTemplate 引擎,当然你也可以配置使用其他模板引擎,如 Jinja2 或 Mako。

配置模板引擎

Bottle 支持内置的 SimpleTemplate 引擎。如果你需要使用其他模板引擎,可以通过配置来更改。例如,下面是如何使用 Jinja2 模板引擎的配置方法:

from bottle import Bottle, template, jinja2_template# 使用 Jinja2 模板引擎
app = Bottle()@app.route('/hello/<name>')
def hello(name):return jinja2_template('hello.html', name=name)app.run(host='localhost', port=8080)

在这个例子中,我们使用 jinja2_template 渲染一个 Jinja2 模板文件 hello.html,并传递了一个变量 name

渲染模板

使用 template 函数来渲染模板文件。模板文件通常存储在一个单独的目录中,可以使用 bottle.TEMPLATE_PATH 来配置模板的搜索路径。

基本示例:
from bottle import Bottle, templateapp = Bottle()@app.route('/hello/<name>')
def hello(name):return template('hello', name=name)app.run(host='localhost', port=8080)
hello.tpl:
<!DOCTYPE html>
<html>
<head><title>Hello Page</title>
</head>
<body><h1>Hello, {{name}}!</h1>
</body>
</html>

在这个例子中,hello 是一个模板文件,它会被渲染并返回给用户。模板中的 {{name}} 会被传入的参数值替换。

模板语法

Bottle 使用的是一个非常简洁的模板语法,支持常见的控制结构,如条件语句、循环等。

  • 变量插值: {{variable}}
  • 条件语句: {% if condition %} ... {% endif %}
  • 循环语句: {% for item in items %} ... {% endfor %}
示例:
<!DOCTYPE html>
<html>
<head><title>Items List</title>
</head>
<body><h1>Items:</h1><ul>{% for item in items %}<li>{{item}}</li>{% endfor %}</ul>
</body>
</html>
Python 代码:
from bottle import Bottle, templateapp = Bottle()@app.route('/items')
def show_items():items = ['Apple', 'Banana', 'Cherry']return template('items', items=items)app.run(host='localhost', port=8080)

此示例中,items 列表中的每个元素都会被渲染为一个 <li> 标签。

模板继承

模板继承是一种让页面共享布局的方式,避免了在多个模板文件中重复相同的代码。可以通过 blockextends 来实现模板的继承。

父模板:
<!-- layout.tpl -->
<!DOCTYPE html>
<html>
<head><title>{{title}}</title>
</head>
<body><header><h1>{{title}}</h1></header><main>{% block content %} {% endblock %}</main>
</body>
</html>
子模板:
<!-- home.tpl -->
{% extends "layout.tpl" %}{% block content %}<p>Welcome to the homepage!</p>
{% endblock %}
Python 代码:
from bottle import Bottle, templateapp = Bottle()@app.route('/')
def home():return template('home', title="Home Page")app.run(host='localhost', port=8080)

在这个例子中,home.tpl 继承了 layout.tpl 模板,且只有内容部分被替换。

静态文件服务

在 Web 应用中,静态文件(如 CSS、JavaScript 和图像文件)通常不需要经过动态生成,而是直接从服务器返回。Bottle 提供了非常简便的方式来服务这些静态文件。

静态文件服务

Bottle 提供了 static_file() 函数来服务静态文件。你可以为静态文件指定一个路由,并将静态文件的路径作为响应返回。

from bottle import Bottle, static_fileapp = Bottle()# 处理静态文件请求
@app.route('/static/<filename>')
def server_static(filename):return static_file(filename, root='./static')app.run(host='localhost', port=8080)

在这个例子中,我们将所有对 /static/ 路径的请求映射到本地 ./static 文件夹中的文件。比如,当访问 http://localhost:8080/static/style.css 时,服务器会返回 ./static/style.css 文件的内容。

处理静态文件的目录结构

通常,Web 应用的静态文件会存放在 static 文件夹中。为了方便管理,建议将静态资源与应用代码分开存放。

project/
│
├── app.py
└── static/├── images/├── css/└── js/

在此结构中,static/images/ 存放图片文件,static/css/ 存放 CSS 文件,static/js/ 存放 JavaScript 文件。你可以按需配置路由来访问这些资源。

使用静态文件

假设你有一个 CSS 文件 style.css,你可以在 HTML 模板中使用它:

<!DOCTYPE html>
<html>
<head><link rel="stylesheet" href="/static/css/style.css"><title>My Web App</title>
</head>
<body><h1>Welcome to My Web App</h1>
</body>
</html>

当访问此 HTML 页面时,浏览器会向 /static/css/style.css 路径发出请求,Bottle 会返回位于 ./static/css/style.css 的文件内容。

高级功能

Bottle 是一个轻量级的 Python Web 框架,设计简洁且功能丰富。在本篇教程中,我们将深入探讨 Bottle 的一些高级功能,帮助你更高效地构建 Web 应用。我们将着重介绍以下内容:

  • 中间件(Middleware):在请求和响应的过程中插入自定义操作。
  • 插件系统:如何使用和创建插件,扩展 Bottle 的功能。
  • 请求和响应钩子:处理请求前后或响应前后的自定义操作。
  • 错误处理:如何处理常见的 HTTP 错误和自定义错误。
  • JSON 数据处理:如何处理 JSON 请求和响应。
  • Session 管理:如何处理会话存储,保持用户状态。

这些功能能够帮助你在实际项目中更加高效地管理 Web 应用的复杂性。

中间件(Middleware)

中间件是在请求和响应的过程中,拦截请求或修改响应的一段代码。Bottle 本身提供了基本的中间件支持,可以通过 install() 方法注册中间件。

使用中间件记录日志

我们可以编写一个简单的中间件,用于记录每个请求的信息(例如请求方法、路径、响应状态等)。

from bottle import Bottle, request, response, run
import loggingapp = Bottle()# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')# 定义日志中间件
def log_request(app):def wrapper(environ, start_response):# 请求前记录日志logging.info(f"{request.method} {request.path}")return app(environ, start_response)return wrapper# 注册中间件
app.install(log_request)@app.route('/')
def home():return "Welcome to Bottle with Middleware!"run(app, host='localhost', port=8080)

在这个例子中,每当一个请求到达时,log_request 中间件会记录下请求的方法和路径。你可以扩展该中间件来记录更多的信息,例如响应状态码或请求头。

使用中间件处理 CORS

跨源资源共享(CORS)是 Web 开发中的一个常见问题。我们可以使用中间件来处理 CORS 头部,允许跨域访问:

def enable_cors(app):def wrapper(environ, start_response):response.headers['Access-Control-Allow-Origin'] = '*'response.headers['Access-Control-Allow-Headers'] = 'Content-Type'response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'return app(environ, start_response)return wrapper# 注册 CORS 中间件
app.install(enable_cors)

这个中间件将为所有响应添加 CORS 相关的头部,使得浏览器可以从不同的域名发起请求。

插件系统

Bottle 提供了一个插件系统,允许开发者扩展框架功能。你可以使用内置插件,也可以编写自己的插件。

使用 Bottle 插件

Bottle 提供了多个内置插件来简化常见的任务,比如数据库连接、Session 管理等。以下是使用 Bottle 的 simplejson 插件来处理 JSON 数据的例子:

from bottle import Bottle, request, response
from bottle import pluginapp = Bottle()@plugin(name='json')
def json_plugin(callback):def wrapper(*args, **kwargs):if request.content_type == 'application/json':request.json = request.json()return callback(*args, **kwargs)return wrapperapp.install(json_plugin)@app.route('/json', method='POST')
def json_example():data = request.jsonreturn {'received': data}run(app, host='localhost', port=8080)
创建自定义插件

你也可以创建自己的插件。一个插件通常是一个可以安装的类,并且可以通过 app.install() 方法进行注册。

from bottle import Bottle, responseclass MyPlugin:def apply(self, callback, route):def wrapper(*args, **kwargs):response.headers['X-My-Plugin'] = 'Active'return callback(*args, **kwargs)return wrapperapp = Bottle()@app.route('/test')
def test():return "Plugin is working!"# 安装插件
app.install(MyPlugin())run(app, host='localhost', port=8080)

在这个例子中,我们创建了一个名为 MyPlugin 的插件,它会在响应中添加一个自定义的 HTTP 头 X-My-Plugin: Active

请求和响应钩子

请求和响应钩子是 Bottle 的重要特性,可以让你在请求处理的不同阶段执行代码。Bottle 提供了以下几种钩子:

  • before_request:在请求处理之前执行。
  • after_request:在请求处理之后执行。
  • error:当发生错误时执行。
before_request 和 after_request 示例
from bottle import Bottle, request, response, runapp = Bottle()# before_request 钩子
@app.hook('before_request')
def before_request():response.headers['X-Request-Time'] = 'Started'# after_request 钩子
@app.hook('after_request')
def after_request():response.headers['X-Response-Time'] = 'Ended'@app.route('/')
def home():return "Hello, Bottle!"run(app, host='localhost', port=8080)

在这个例子中,before_request 钩子在请求到来时设置一个自定义的头部 X-Request-Time,而 after_request 钩子在响应发送之前设置一个 X-Response-Time

错误处理钩子

你还可以定义一个错误处理钩子来捕获应用中的异常并返回自定义的错误响应:

@app.hook('error')
def handle_error(error):return {"error": str(error.status_code), "message": error.body}

JSON 数据处理

Bottle 在处理 JSON 数据时非常方便。你可以使用 request.json 属性获取请求体中的 JSON 数据,也可以使用 response.json 返回 JSON 响应。

解析 JSON 请求
@app.route('/post_json', method='POST')
def post_json():data = request.jsonreturn {"received": data}

当客户端发送 JSON 数据时,request.json 会自动解析并将其转换为 Python 字典对象。

返回 JSON 响应
@app.route('/json_response')
def json_response():data = {"message": "Hello, JSON!"}response.content_type = 'application/json'return data

通过设置 response.content_type = 'application/json',你可以明确地告诉客户端返回的数据是 JSON 格式。

Session 管理

在 Web 应用中,Session 是一种常见的状态管理方式。Bottle 提供了一个内置的 Session 插件,支持在客户端使用 cookie 存储会话数据。

使用 Session 插件
from bottle import Bottle, request, response, run
from bottle import default_app
from bottle import sessionapp = Bottle()# 使用 session 插件
@app.route('/login', method='POST')
def login():session['username'] = request.forms.get('username')return {"message": "Logged in!"}@app.route('/profile')
def profile():username = session.get('username')if username:return {"message": f"Hello, {username}!"}else:response.status = 403return {"error": "Not logged in!"}app.config['session'] = {'secret_key': 'supersecretkey'}
run(app, host='localhost', port=8080)

在这个例子中,我们使用了 session 对象来存储用户的登录信息。用户登录时,用户名会被存储在 session 中,而访问 /profile 时,系统会检查用户是否已登录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/5452.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Qt桌面应用开发 第二天(信号和槽 Lambda表达式)

目录 1.信号和槽 1.1信号 1.2信号和槽重载问题 1.3 注意事项 1.4信号和槽Lambda表达式 1.信号和槽 信号的发送者——信号——信号的接受者——信号的处理&#xff08;槽函数&#xff09; connect(信号的发送者&#xff0c;发送的信号&#xff0c;信号的接受者&#xff0…

ubuntu 22.04 server 安装 anaconda3

ubuntu 22.04 server 安装 anaconda3 https://www.anaconda.com/download/success Anaconda Installers wget https://repo.anaconda.com/archive/Anaconda3-2024.10-1-Linux-x86_64.sh 其他的是 默认 Executing transaction: done installation finished. Do you wish to…

如何设置VSCODE快捷键光标移到行首和行尾

{ "key": "cmdhome", "command": "cursorTop", },{ "key": "cmdend", "command": "cursorBottom", }

台新金控在台北金融科技展上展示自研GenAI应用与LLM

在今年的台北金融科技展上&#xff0c;多家金融机构展示了他们的生成式人工智能&#xff08;GenAI&#xff09;应用。其中&#xff0c;台新金控也展示了包括升级后的智能客服、面向企业金融客户的拟真客服人员、影片生成服务以及音乐生成服务等应用。 然而&#xff0c;台新的亮…

项目开发流程规范文档

项目开发流程规范文档 目标: 明确项目组中需求管理人员, 交互设计, 美工以及开发之间的工作输入输出产物. 明确各岗位职责. 以免造成开发, 产品经理以及项目经理之间理解不到位, 沟通成本过高,返工造成资源浪费. 所有环节产生的文档都可以作为项目交付的资源. 而不是事后再补文…

Go API 多种响应的规范化处理和简化策略

一个对外提供API接口的服务&#xff0c;在真正动工开发接口前一般需要先确定一下接口响应的通用格式&#xff0c;无论接口响应里返不返回业务数据&#xff0c;返回的数据是字符串、列表、对象还是其他类型都会遵照这个通用的响应格式。 既然一个项目接口的响应格式是确定的&…

poi excel数据统计导出

##poi excel导出案例 1.ajxa导出请求没有任何反应&#xff0c;打断点看了workBook中也有数据&#xff0c;网上查阅说ajax请求导出无法接收流&#xff0c;换成location.href,果然可以了 2.控制器代码 response.setCharacterEncoding("UTF-8");response.setContentTyp…

基于Python的影院电影购票系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

SQL Server 多数据源配置

目录 1、添加依赖 2. 配置数据源 3. 创建数据源配置类 4. 创建Mapper接口和XML映射文件 5. 使用Mapper 6.启动类配置 7.项目结构目录 1、添加依赖 首先&#xff0c;在pom.xml文件中添加SQL Server的JDBC驱动&#xff1a; <!-- SQL Server Connector --> <dep…

FlinkSql读取外部Mysql和HBase数据库的方法(scala)

我的Flink版本为1.13.6 <flink.version>1.13.6</flink.version> FlinkSql读取外部的MySQL是走的JDBC所以需要以下两个依赖&#xff1a; <dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-jdbc_${scala.bina…

使用Rust实现http/https正向代理

相关库的安装 利用vcpkg安装openssl库 vcpkg install openssl:x64-windows并设置openssl库位置的环境变量 $Env:OPENSSL_DIR"D:/vcpkg/packages/openssl_x64-windows/"安装openssl软件&#xff0c;因为需要利用openssl生成自签名证书 Cargo依赖 [dependencies] …

vue3如何使用pinia设置全局状态,附常见面试题

1. stores/index.ts 文件 在 index.ts 中创建 store 实例并封装了注册逻辑&#xff0c;这样可以方便地将整个 Pinia 实例注册到 Vue 应用中。代码如下&#xff1a; import type { App } from vue import { createPinia } from piniaconst store createPinia()// 全局注册 st…

【微知】Nvida Mellanox网卡中速率SDR、DDR、QDR、FDR、EDR、HDR、NDR全称与速率?

文章目录 综述背景全称早期速率&#xff1a;中期当前 其他 综述 Single Data Rate (SDR) 10Gbps Double Data Rate (DDR) 20Gbps Quad Data Rate (QDR) 40Gbps Fourteen Data Rate (FDR) 56Gbps Enhanced Data Rate (EDR) 100Gbps High Data Rate (HDR) 200Gbps Next Data Rat…

融合虚拟化与容器技术,打造灵活又安全的AI算力服务

随着人工智能技术的不断进步&#xff0c;AI企业在迅速推进大模型业务时&#xff0c;往往会倾向于采用容器化的轻量部署方案。相较于传统的虚拟机部署&#xff0c;容器化在快速部署、资源利用、环境一致性和自动化编排等方面具备显著优势。 然而&#xff0c;容器技术所固有的隔…

Hunyuan-Large:推动AI技术进步的下一代语言模型

腾讯近期推出了基于Transformer架构的混合专家&#xff08;MoE&#xff09;模型——Hunyuan-Large&#xff08;Hunyuan-MoE-A52B&#xff09;。该模型目前是业界开源的最大MoE模型之一&#xff0c;拥有3890亿总参数和520亿激活参数&#xff0c;展示了极强的计算能力和资源优化优…

岛屿数量 广搜版BFS C#

和之前的卡码网深搜版是一道题 力扣第200题 99. 岛屿数量 题目描述 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成&#xff0c;并且四周都是水域。…

本地使用conda创建django虚拟环境

1、首先本地安装好conda。 2、创建django的虚拟环境 conda create -n django # 这里的 django只是虚拟的名称&#xff0c;自己随便名字就行&#xff0c;只要你自己知道这个是django的虚拟环境就行。 3、安装成功&#xff0c;查看虚拟环境 conda env list 4、激活虚拟环境…

rabbitMQ

官网&#xff1a;https://www.rabbitmq.com/ 一 介绍与安装 1 安装 我们同样基于Docker来安装RabbitMQ&#xff0c;使用下面的命令即可&#xff1a; docker run \-e RABBITMQ_DEFAULT_USERitheima \-e RABBITMQ_DEFAULT_PASS123321 \-v mq-plugins:/plugins \--name rabbi…

reg注册表研究与物理Hack

reg注册表研究与物理Hack 声明&#xff1a;内容的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 目录 reg注册表研究与物理HackWindows注册表修改注册表实现应用程序开机…

【黑盒测试】等价类划分法及实例

本文主要介绍黑盒测试之等价类划分法&#xff0c;如什么是等价类划分法&#xff0c;以及如何划分&#xff0c;设计等价类表。以及关于三角形案例的等价类划分法。 文章目录 一、什么是等价类划分法 二、划分等价类和列出等价类表 三、确定等价类的原则 四、建立等价类表 …