推荐使用最新版本的 Python,Flask 3.1.x 要求 Python 3.9+,建议使用 3.13/3.14
当安装 Flask 时,以下配套软件会被自动安装:
flask 命令,并允许添加自定义管理命令以下配套软件不会被自动安装。如果安装了,那么 Flask 会检测到这些软件:
flask 命令时为通过 dotenv 设置环境变量提供支持在已激活的虚拟环境中使用 pip 安装 Flask:
pip install Flask最简单的 Flask 应用:
from flask import Flask
# 创建 Flask 应用实例
# __name__ 是一个适用于大多数情况的快捷方式,Flask 以此来确定应用的根目录
app = Flask(__name__)
# 使用 route() 装饰器来告诉 Flask 触发函数的 URL
@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"说明:
Flask 类__name__ 参数帮助 Flask 找到模板和静态文件@app.route() 装饰器将 URL 路径 / 绑定到 hello_world 函数将以上代码保存为 hello.py(避免使用 flask.py,会与 Flask 本身冲突)
使用 flask 命令来运行应用。使用 --app 选项指定应用的位置
flask --app hello run捷径: 如果文件名是
app.py或wsgi.py,则无需使用--app选项
这会启动一个内置的开发服务器。在浏览器中打开 http://127.0.0.1:5000/,您应该能看到 "Hello, World!"
警告: 如果 5000 端口被占用,您会看到
OSError: [Errno 98]或OSError: [WinError 10013]的错误。您可以使用flask run --port=5001来指定其他端口
开启调试模式后,服务器会在代码更改后自动重启,并在发生错误时提供一个交互式调试器。
flask --app hello run --debug安全警告: 永远不要在生产环境中开启调试模式
使用 @app.route() 装饰器将函数绑定到 URL
可以在 URL 中添加变量,并将变量作为关键字参数传递给函数
from markupsafe import escape
@app.route('/user/<username>')
def show_user_profile(username):
# 使用 escape() 来防止 XSS 攻击
return f'User {escape(username)}'
@app.route('/post/<int:post_id>')
def show_post(post_id):
# post_id 是一个整数
return f'Post {post_id}'
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# subpath 可以包含斜杠
return f'Subpath {escape(subpath)}'转换器类型:
| 类型 | 描述 |
|---|---|
string | (默认) 接受任何不包含斜杠的文本 |
int | 接受正整数 |
float | 接受正浮点数 |
path | 类似 string,但可以包含斜杠 |
uuid | 接受 UUID 字符串 |
使用 url_for() 函数来构建 URL,而不是在代码中硬编码
优点:
from flask import url_for
with app.test_request_context():
print(url_for('hello_world'))
print(url_for('show_user_profile', username='John Doe'))默认情况下路由只响应 GET 请求。可以使用 methods 参数来处理不同的 HTTP 方法
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
# 处理登录逻辑
return do_the_login()
else:
# 显示登录表单
return show_the_login_form()或者使用便捷的装饰器:
@app.get('/login')
def login_get():
return show_the_login_form()
@app.post('/login')
def login_post():
return do_the_login()Flask 使用 Jinja2 模板引擎。在 templates 文件夹中创建 HTML 文件
项目结构:
/myproject
/app.py
/templates
/hello.html示例:
from flask import render_template
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)templates/hello.html:
<!DOCTYPE html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello, World!</h1>
{% endif %}注意: Jinja2 会自动转义 HTML,防止 XSS 攻击。如果需要输出原始 HTML,请使用
|safe过滤器
request 对象包含了客户端的请求信息
request.form: 访问表单数据 (POST/PUT)request.args: 访问 URL 查询参数 (GET)request.method: 获取当前的请求方法request.files: 访问上传的文件from flask import request
@app.route('/login', methods=['POST'])
def login():
username = request.form['username']
password = request.form['password']
# ...在 HTML 表单中设置 enctype="multipart/form-data"
from flask import request
from werkzeug.utils import secure_filename
@app.route('/upload', methods=['POST'])
def upload_file():
if 'the_file' in request.files:
f = request.files['the_file']
# 使用 secure_filename 保证文件名安全
f.save(f"/var/www/uploads/{secure_filename(f.filename)}")
return 'File uploaded successfully'使用 request.cookies 读取 cookies,使用响应对象的 set_cookie() 方法设置 cookies
from flask import make_response, request
@app.route('/')
def index():
username = request.cookies.get('username')
resp = make_response(render_template('index.html'))
resp.set_cookie('username', 'the username')
return respredirect(url_for(...)): 重定向到其他 URLabort(404): 中断请求并返回错误代码from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('login'))
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404直接从视图返回字典或列表,Flask 会自动将其转换为 JSON 响应。
@app.route("/me")
def me_api():
user = get_current_user()
return {
"username": user.username,
"theme": user.theme,
}对于更复杂的序列化,可以使用 jsonify() 函数
session 对象允许在不同请求之间存储信息。它使用加密的 cookie
必须设置 secret_key:
from flask import Flask, session, redirect, url_for, request
app = Flask(__name__)
# 密钥必须是随机且保密的
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
@app.route('/')
def index():
if 'username' in session:
return f'Logged in as {session["username"]}'
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
session.pop('username', None)
return redirect(url_for('index'))Q1: 如何生成一个好的 secret_key?
A1: 使用 Python 的 secrets 模块来生成一个安全的随机密钥。
import secrets
secrets.token_hex(16)Q2: 为什么我的应用无法从网络中的其他计算机访问?
A2: 默认情况下,开发服务器只监听本地回环地址 (127.0.0.1)。要使其公开访问,请使用 --host=0.0.0.0。
flask run --host=0.0.0.0Q3: 如何处理静态文件,如 CSS 和 JavaScript?
A3: 在应用根目录下创建一个名为 static 的文件夹。文件将通过 /static/filename URL 访问。在模板中使用 url_for('static', filename='style.css') 来生成 URL。
secret_key 的私密性: 不要将其硬编码在代码中,而是从环境变量加载| 特性 | 本文编写时 | 当前(Flask 3.1.x) |
|---|---|---|
| 版本基线 | Flask 2.x | 3.1 为最新稳定版;要求 Python 3.9+ |
| 异步视图 | 部分支持 | 3.0 起原生支持 async 视图(无需额外扩展) |
| CLI | flask run | 3.x 默认启用 debugger/pin;FLASK_DEBUG 等环境变量不变 |
| 依赖 | — | 3.x 依赖 Werkzeug 3.x;app.json/config 方式不变 |
| 安全性 | — | 3.x 强化 cookie 与会话默认值 |
本文讲解的路由、模板、表单、数据库集成等核心模式在 Flask 3.x 中完全适用;升级主要关注 Python 3.9+ 要求与异步视图支持。