Flask 路由和 URL
- 基本路由
- 动态路由
- 自定义转换器
- 路由参数
- [`url_for` 和 `redirct` 函数](#
url_for
和redirct
函数) - 请求参数
-
- [查询字符串参数(Query String Parameters)](#查询字符串参数(Query String Parameters))
- [表单数据(Form Data)](#表单数据(Form Data))
- [JSON 数据](#JSON 数据)
- 文件上传
在 Flask 中,路由(Routing)是将 URL 路径映射到视图函数(View Functions)的过程。这允许 Flask 应用程序知道当接收到某个 URL 请求时应该调用哪个函数来处理该请求。路由是通过 Flask 应用实例上的装饰器来定义的,最常用的装饰器是 @app.route()
。
基本路由
python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
在这个例子中,@app.route('/')
装饰器将根 URL /
映射到了 home
函数。当 Flask 应用程序接收到对根 URL 的请求时,它将调用 home
函数并返回其响应。
在 Flask 中,动态路由和自定义转换器是两个强大的特性,它们允许你以灵活的方式定义 URL 规则。
动态路由
动态路由是指 URL 规则中包含变量部分,这些变量部分可以根据请求的实际 URL 来动态地匹配和提取。在 Flask 中,你可以通过在 URL 规则中使用尖括号 <variable_name>
来定义动态路由。默认情况下,变量部分会匹配不包含斜杠的任意文本(即使用 string
转换器)。
例如:
python
@app.route('/user/<username>')
def user_profile(username):
# username 会根据请求的 URL 动态地匹配并传递给视图函数
return f'User Profile for {username}'
自定义转换器
虽然 Flask 提供了一些默认的转换器(如 string
、int
、float
、path
、uuid
),但你可能需要更复杂的匹配逻辑。这时,你可以通过继承 werkzeug.routing.BaseConverter
并实现 to_python
和 to_url
方法来创建自定义转换器。
自定义转换器允许你定义变量部分应该如何被解析(to_python
)以及如何将变量转换回 URL 的一部分(to_url
,尽管在许多情况下可能不需要实现此方法)。
下面是一个自定义转换器的例子,它用于匹配由字母和数字组成的用户名,且长度在 4 到 20 个字符之间:
python
from werkzeug.routing import BaseConverter
from flask import Flask
class RegexConverter(BaseConverter):
def __init__(self, url_map, regex):
super(RegexConverter, self).__init__(url_map)
self.regex = regex
def to_python(self, value):
# 可以在这里进行额外的验证或处理
return value
def to_url(self, value):
# 在这个例子中,我们不需要对值进行任何修改来匹配 URL
# 但如果有需要,可以在这里进行格式化
return value
app = Flask(__name__)
app.url_map.converters['re'] = RegexConverter
@app.route('/user/<re(r"^[a-zA-Z0-9]{4,20}$"):username>')
def user_profile(username):
return f'User Profile for {username}'
if __name__ == '__main__':
app.run(debug=True)
在这个例子中,我们定义了一个 RegexConverter
转换器,它接受一个正则表达式作为参数。然后,我们在 Flask 应用中注册了这个转换器,并将其命名为 re
。之后,在路由定义中,我们使用 <re("正则表达式"):变量名>
的形式来指定使用我们的自定义转换器。在这个例子中,正则表达式用于匹配由 4 到 20 个字母或数字组成的用户名。
请注意,正则表达式字符串在 re
函数中是一个原始字符串(由 r
前缀标识),这是为了防止 Python 字符串中的反斜杠被解释为转义字符。
路由参数
路由装饰器可以接受额外的参数来修改路由的行为。
methods
:指定该路由响应的 HTTP 方法(如 GET、POST)。defaults
:为视图函数提供默认值。strict_slashes
:控制 Flask 是否严格遵循尾随斜杠的规则。
python
@app.route('/project/<int:project_id>', methods=['GET', 'POST'])
def project(project_id):
# 处理项目 ID 为 project_id 的项目
return f'Project {project_id}'
@app.route('/about', strict_slashes=False)
def about():
return 'About the site'
在这个例子中,project
函数可以处理对 /project/<project_id>
的 GET 和 POST 请求,其中 <project_id>
被指定为整数类型。about
函数展示了如何设置 strict_slashes=False
来允许 URL 尾随或不尾随斜杠。
url_for
和 redirct
函数
在 Flask 中,url_for
和 redirect
函数经常一起使用,以实现 URL 的动态生成和页面重定向。这两个函数在构建动态和可维护的 Web 应用时非常有用。
url_for
url_for
函数是 Flask 提供的一个用于构建 URL 的工具。它允许你根据端点名(endpoint)和可选的参数来生成 URL。端点名通常是视图函数的名称,但也可以是你在注册蓝图或路由时指定的任何名称。
使用 url_for
的好处之一是它可以根据你的应用配置动态地生成 URL,比如当应用部署在不同的子路径下时。此外,它还可以处理 URL 编码,确保生成的 URL 是有效的。
redirect
redirect
函数用于将用户重定向到另一个 URL。它接受一个 URL 字符串作为参数,并返回一个 HTTP 重定向响应(通常是 302 状态码)。在 Flask 中,当你想要在用户提交表单后显示一个新的页面,或者在用户未登录时重定向到登录页面时,这个函数非常有用。
结合使用
由于 redirect
需要一个 URL 字符串作为参数,而 url_for
可以动态地生成这个 URL 字符串,因此它们经常一起使用。这样做的好处是,你可以保持 URL 的灵活性和可维护性,因为你可以通过更改路由的端点名或参数来更新 URL,而无需在代码中硬编码 URL 字符串。
下面是一个结合使用 url_for
和 redirect
的示例:
python
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.route('/')
def home():
# 使用 url_for 生成 /about 的 URL,并将其传递给 redirect 函数
return redirect(url_for('about'))
@app.route('/about')
def about():
return 'This is the about page'
if __name__ == '__main__':
app.run(debug=True)
在这个例子中,当用户访问根 URL(/
)时,home
视图函数会被调用。它使用 url_for('about')
生成 /about
路由的 URL,并将这个 URL 传递给 redirect
函数。然后,redirect
函数返回一个 HTTP 重定向响应,告诉浏览器加载 /about
路由对应的页面。
通过这种方式,你可以确保你的 Flask 应用中的 URL 是灵活且易于维护的
请求参数
在 Flask 中,处理请求参数是一个常见的任务,尤其是在构建 Web 应用程序时。Flask 提供了几种方式来访问请求中的参数,包括查询字符串(query string)、表单数据(form data)、JSON 数据以及文件上传等。这些参数可以通过 Flask 的 request
对象来访问,该对象是 Flask 应用上下文中全局可访问的。
查询字符串参数(Query String Parameters)
查询字符串参数是附加在 URL 后面的键值对,以问号(?
)开头,并通过与号(&
)分隔。在 Flask 中,你可以使用 request.args.get('key', default)
方法来获取查询字符串参数的值。如果参数不存在,则返回默认值(如果提供的话)。
python
from flask import Flask, request
app = Flask(__name__)
@app.route('/search')
def search():
query = request.args.get('q', '')
return f'Searching for {query}'
if __name__ == '__main__':
app.run(debug=True)
表单数据(Form Data)
表单数据通常是通过 HTML 表单提交的,可以是 GET 或 POST 请求。在 Flask 中,你可以使用 request.form['key']
来获取 POST 请求中的表单数据。如果参数不存在,将会抛出一个 KeyError
,因此你可能需要使用 get
方法来避免这种情况。
python
from flask import Flask, request
app = Flask(__name__)
@app.route('/submit', methods=['POST'])
def submit_form():
name = request.form['name']
return f'Hello, {name}!'
if __name__ == '__main__':
app.run(debug=True)
JSON 数据
对于 API 来说,JSON 数据是一种常见的请求和响应格式。在 Flask 中,你可以通过 request.json
来获取以 JSON 格式发送的请求体数据。注意,request.json
会自动将 JSON 字符串解析为 Python 字典。
python
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/data', methods=['POST'])
def handle_data():
data = request.json
return jsonify({'received': data}), 200
if __name__ == '__main__':
app.run(debug=True)
文件上传
Flask 也支持文件上传。你可以通过 request.files['file']
来访问上传的文件,其中 'file'
是 HTML 表单中 <input type="file">
元素的 name
属性值。
python
from flask import Flask, request
import os
app = Flask(__name__)
UPLOAD_FOLDER = '/path/to/uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return 'No file part'
file = request.files['file']
if file.filename == '':
return 'No selected file'
if file:
filename = file.filename
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(file_path)
return f'File {filename} uploaded successfully'
if __name__ == '__main__':
app.run(debug=True)
在处理请求参数时,请确保你的应用能够安全地处理各种输入,以防止跨站脚本(XSS)、SQL 注入等安全漏洞。