Python Flask 框架使用指南 #
一、Flask简介 #
Flask是一个轻量级的Python Web框架,以其简洁、灵活和易用性而闻名。它基于Werkzeug WSGI工具包和Jinja2模板引擎,被广泛用于构建Web应用和API。
1.1 Flask的特点 #
- 轻量级:核心功能简洁,扩展丰富
- 灵活性:没有强制性的项目结构,可根据需求自由组织
- 易用性:API设计简洁明了,学习曲线平缓
- 扩展性:通过丰富的扩展生态系统,可以轻松添加各种功能
- 适用于小型到中型项目:特别适合快速开发和原型设计
二、Flask安装与环境配置 #
2.1 安装Flask #
bash
# 使用pip安装Flask
pip install flask
# 安装特定版本
pip install flask==3.0.3
# 安装开发版本
pip install flask --pre
2.2 创建虚拟环境 #
bash
# 创建虚拟环境
python -m venv myflaskenv
# 激活虚拟环境
# Windows
myflaskenv\Scripts\activate
# macOS/Linux
source myflaskenv/bin/activate
# 退出虚拟环境
deactivate
2.3 项目结构推荐 #
text
myflaskapp/
├── app/
│ ├── __init__.py
│ ├── routes.py
│ ├── models.py
│ ├── forms.py
│ ├── templates/
│ └── static/
├── requirements.txt
└── run.py
三、Flask基础入门 #
3.1 第一个Flask应用 #
创建hello.py文件:
python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, Flask!'
if __name__ == '__main__':
app.run(debug=True)
运行应用:
bash
python hello.py
访问http://localhost:5000查看结果。
3.2 路由与视图函数 #
python
# 基本路由
@app.route('/')
def index():
return '首页'
# 带参数的路由
@app.route('/user/<username>')
def show_user_profile(username):
return f'用户 {username}'
# 带类型的参数
@app.route('/post/<int:post_id>')
def show_post(post_id):
return f'帖子 {post_id}'
# 多个HTTP方法
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return '登录处理'
else:
return '登录表单'
3.3 URL构建 #
python
from flask import url_for
# 构建URL
@app.route('/')
def index():
return url_for('login') # 返回 /login
@app.route('/login')
def login():
return 'login'
@app.route('/user/<username>')
def profile(username):
return f'{username}\s profile'
with app.test_request_context():
print(url_for('index')) # /
print(url_for('login')) # /login
print(url_for('profile', username='张三')) # /user/张三
print(url_for('profile', username='张三', next='/')) # /user/张三?next=/
四、模板引擎与视图渲染 #
4.1 模板目录结构 #
text
app/
└── templates/
├── base.html
├── index.html
└── user/
└── profile.html
4.2 基本模板使用 #
base.html(基础模板):
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Flask应用{% endblock %}</title>
</head>
<body>
<nav>
<a href="{{ url_for('index') }}">首页</a>
<a href="{{ url_for('about') }}">关于</a>
</nav>
{% block content %}{% endblock %}
<footer>
<p>© 2026 Flask应用</p>
</footer>
</body>
</html>
index.html(继承基础模板):
html
{% extends "base.html" %}
{% block title %}首页 - Flask应用{% endblock %}
{% block content %}
<h1>欢迎来到Flask应用</h1>
<p>这是首页内容</p>
<!-- 循环示例 -->
<h2>用户列表</h2>
<ul>
{% for user in users %}
<li><a href="{{ url_for('profile', username=user.username) }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
<!-- 条件示例 -->
{% if current_user.is_authenticated %}
<p>欢迎回来,{{ current_user.username }}!</p>
{% else %}
<p>请 <a href="{{ url_for('login') }}">登录</a></p>
{% endif %}
{% endblock %}
4.3 渲染模板 #
python
from flask import render_template
@app.route('/')
def index():
users = [{'username': '张三'}, {'username': '李四'}]
return render_template('index.html', users=users)
@app.route('/about')
def about():
return render_template('about.html', title='关于我们')
4.4 模板过滤器 #
python
# 自定义过滤器
@app.template_filter('capitalize')
def capitalize_filter(s):
if not isinstance(s, str):
return s
return s.capitalize()
# 在模板中使用
# {{ name|capitalize }}
五、表单处理 #
5.1 使用Flask-WTF扩展 #
安装扩展:
bash
pip install flask-wtf
5.2 创建表单类 #
python
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired, Length, Email, EqualTo
class RegistrationForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired(), Length(min=2, max=20)])
email = StringField('邮箱', validators=[DataRequired(), Email()])
password = PasswordField('密码', validators=[DataRequired()])
confirm_password = PasswordField('确认密码', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('注册')
class LoginForm(FlaskForm):
email = StringField('邮箱', validators=[DataRequired(), Email()])
password = PasswordField('密码', validators=[DataRequired()])
remember = BooleanField('记住我')
submit = SubmitField('登录')
5.3 处理表单提交 #
python
from flask import flash, redirect, url_for
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
# 处理注册逻辑
flash(f'账户创建成功,欢迎 {form.username.data}!', 'success')
return redirect(url_for('login'))
return render_template('register.html', title='注册', form=form)
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
# 处理登录逻辑
if form.email.data == 'admin@example.com' and form.password.data == 'password':
flash('登录成功!', 'success')
return redirect(url_for('index'))
else:
flash('登录失败,请检查邮箱和密码', 'danger')
return render_template('login.html', title='登录', form=form)
5.4 模板中的表单渲染 #
html
{% extends "base.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">注册账户</legend>
<div class="form-group">
{{ form.username.label(class="form-control-label") }}
{% if form.username.errors %}
{{ form.username(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.email.label(class="form-control-label") }}
{% if form.email.errors %}
{{ form.email(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.email.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.email(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.password.label(class="form-control-label") }}
{% if form.password.errors %}
{{ form.password(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.confirm_password.label(class="form-control-label") }}
{% if form.confirm_password.errors %}
{{ form.confirm_password(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.confirm_password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.confirm_password(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
<div class="border-top pt-3">
<small class="text-muted">
已有账户? <a class="ml-2" href="{{ url_for('login') }}">登录</a>
</small>
</div>
{% endblock content %}
六、数据库集成 #
6.1 使用Flask-SQLAlchemy扩展 #
安装扩展:
bash
pip install flask-sqlalchemy
6.2 配置数据库 #
python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# SQLite配置
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
# MySQL配置
# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://user:password@localhost/db_name'
# PostgreSQL配置
# app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://user:password@localhost/db_name'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
6.3 定义模型 #
python
from datetime import datetime
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
password = db.Column(db.String(60), nullable=False)
posts = db.relationship('Post', backref='author', lazy=True)
def __repr__(self):
return f"User('{self.username}', '{self.email}', '{self.image_file}')"
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __repr__(self):
return f"Post('{self.title}', '{self.date_posted}')"
6.4 创建数据库 #
python
# 在Python终端中执行
with app.app_context():
db.create_all()
6.5 数据库操作 #
python
# 添加数据
with app.app_context():
user_1 = User(username='admin', email='admin@example.com', password='password')
db.session.add(user_1)
db.session.commit()
# 查询数据
users = User.query.all()
user = User.query.filter_by(username='admin').first()
user = User.query.get(1)
# 更新数据
user.username = 'new_username'
db.session.commit()
# 删除数据
db.session.delete(user)
db.session.commit()
七、认证与授权 #
7.1 使用Flask-Login扩展 #
安装扩展:
bash
pip install flask-login
7.2 配置Flask-Login #
python
from flask_login import LoginManager
login_manager = LoginManager(app)
login_manager.login_view = 'login' # 登录页面的路由
login_manager.login_message_category = 'info' # 登录消息的Bootstrap类别
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
7.3 扩展User模型 #
python
from flask_login import UserMixin
class User(db.Model, UserMixin):
# 现有字段...
pass
7.4 登录与登出 #
python
from flask_login import login_user, current_user, logout_user, login_required
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user and check_password_hash(user.password, form.password.data):
login_user(user, remember=form.remember.data)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('index'))
else:
flash('登录失败,请检查邮箱和密码', 'danger')
return render_template('login.html', title='登录', form=form)
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
# 保护路由
@app.route('/account')
@login_required
def account():
return render_template('account.html', title='账户信息')
7.5 密码哈希 #
bash
pip install werkzeug
python
from werkzeug.security import generate_password_hash, check_password_hash
# 创建密码哈希
password_hash = generate_password_hash('password', method='pbkdf2:sha256')
# 验证密码
is_valid = check_password_hash(password_hash, 'password')
八、文件上传 #
8.1 配置上传目录 #
python
import os
app.config['UPLOAD_FOLDER'] = 'static/profile_pics'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB
# 允许的文件扩展名
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
8.2 处理文件上传 #
python
from flask import request, url_for, flash
import secrets
from PIL import Image
@app.route('/account', methods=['GET', 'POST'])
@login_required
def account():
form = UpdateAccountForm()
if form.validate_on_submit():
if form.picture.data:
picture_file = save_picture(form.picture.data)
current_user.image_file = picture_file
current_user.username = form.username.data
current_user.email = form.email.data
db.session.commit()
flash('您的账户信息已更新!', 'success')
return redirect(url_for('account'))
elif request.method == 'GET':
form.username.data = current_user.username
form.email.data = current_user.email
image_file = url_for('static', filename='profile_pics/' + current_user.image_file)
return render_template('account.html', title='账户信息', image_file=image_file, form=form)
def save_picture(form_picture):
random_hex = secrets.token_hex(8)
_, f_ext = os.path.splitext(form_picture.filename)
picture_fn = random_hex + f_ext
picture_path = os.path.join(app.root_path, 'static/profile_pics', picture_fn)
# 调整图片大小
output_size = (125, 125)
i = Image.open(form_picture)
i.thumbnail(output_size)
i.save(picture_path)
return picture_fn
九、REST API开发 #
9.1 创建API路由 #
python
from flask import jsonify, request
# 获取所有用户
@app.route('/api/users', methods=['GET'])
def get_users():
users = User.query.all()
output = []
for user in users:
user_data = {
'id': user.id,
'username': user.username,
'email': user.email
}
output.append(user_data)
return jsonify({'users': output})
# 获取单个用户
@app.route('/api/users/<int:id>', methods=['GET'])
def get_user(id):
user = User.query.get_or_404(id)
return jsonify({
'id': user.id,
'username': user.username,
'email': user.email
})
# 创建用户
@app.route('/api/users', methods=['POST'])
def create_user():
data = request.get_json()
hashed_password = generate_password_hash(data['password'], method='pbkdf2:sha256')
new_user = User(username=data['username'], email=data['email'], password=hashed_password)
db.session.add(new_user)
db.session.commit()
return jsonify({'message': '用户创建成功'}), 201
# 更新用户
@app.route('/api/users/<int:id>', methods=['PUT'])
def update_user(id):
user = User.query.get_or_404(id)
data = request.get_json()
user.username = data['username']
user.email = data['email']
db.session.commit()
return jsonify({'message': '用户更新成功'})
# 删除用户
@app.route('/api/users/<int:id>', methods=['DELETE'])
def delete_user(id):
user = User.query.get_or_404(id)
db.session.delete(user)
db.session.commit()
return jsonify({'message': '用户删除成功'})
9.2 使用Flask-RESTful扩展 #
安装扩展:
bash
pip install flask-restful
使用Flask-RESTful:
python
from flask_restful import Api, Resource, reqparse
api = Api(app)
user_parser = reqparse.RequestParser()
user_parser.add_argument('username', required=True, help='用户名不能为空')
user_parser.add_argument('email', required=True, help='邮箱不能为空')
user_parser.add_argument('password', required=True, help='密码不能为空')
class UserResource(Resource):
def get(self, user_id):
user = User.query.get_or_404(user_id)
return {
'id': user.id,
'username': user.username,
'email': user.email
}
def put(self, user_id):
user = User.query.get_or_404(user_id)
args = user_parser.parse_args()
user.username = args['username']
user.email = args['email']
db.session.commit()
return {'message': '用户更新成功'}
def delete(self, user_id):
user = User.query.get_or_404(user_id)
db.session.delete(user)
db.session.commit()
return {'message': '用户删除成功'}
class UserListResource(Resource):
def get(self):
users = User.query.all()
output = []
for user in users:
output.append({
'id': user.id,
'username': user.username,
'email': user.email
})
return {'users': output}
def post(self):
args = user_parser.parse_args()
hashed_password = generate_password_hash(args['password'], method='pbkdf2:sha256')
new_user = User(username=args['username'], email=args['email'], password=hashed_password)
db.session.add(new_user)
db.session.commit()
return {'message': '用户创建成功'}, 201
# 添加API资源
api.add_resource(UserListResource, '/api/users')
api.add_resource(UserResource, '/api/users/<int:user_id>')
十、错误处理 #
10.1 自定义错误页面 #
python
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'), 500
@app.errorhandler(403)
def forbidden(e):
return render_template('403.html'), 403
10.2 错误日志 #
python
import logging
# 配置日志
logging.basicConfig(
filename='flask_app.log',
level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s'
)
# 记录日志
app.logger.debug('这是调试信息')
app.logger.info('这是普通信息')
app.logger.warning('这是警告信息')
app.logger.error('这是错误信息')
app.logger.critical('这是严重错误信息')
十一、部署 #
11.1 生产环境配置 #
python
import os
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard-to-guess-string'
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///site.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
MAIL_SERVER = os.environ.get('MAIL_SERVER')
MAIL_PORT = int(os.environ.get('MAIL_PORT') or 25)
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
MAIL_DEFAULT_SENDER = os.environ.get('MAIL_DEFAULT_SENDER')
app.config.from_object(Config)
11.2 使用Gunicorn #
安装Gunicorn:
bash
pip install gunicorn
运行应用:
bash
gunicorn -w 4 -b 0.0.0.0:5000 run:app
11.3 使用Nginx作为反向代理 #
nginx
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static {
alias /path/to/your/app/static;
}
location /media {
alias /path/to/your/app/media;
}
}
11.4 Docker部署 #
创建Dockerfile:
dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "run:app"]
创建docker-compose.yml:
yaml
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
environment:
- SECRET_KEY=your-secret-key
- DATABASE_URL=sqlite:///site.db
volumes:
- ./site.db:/app/site.db
十二、Flask最佳实践 #
12.1 项目结构 #
采用模块化结构,将应用拆分为多个蓝图。
text
myapp/
├── app/
│ ├── __init__.py
│ ├── main/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── forms.py
│ ├── users/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ ├── forms.py
│ │ └── utils.py
│ ├── posts/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── forms.py
│ ├── models.py
│ ├── templates/
│ └── static/
├── config.py
├── run.py
└── requirements.txt
12.2 使用蓝图 #
python
# app/main/__init__.py
from flask import Blueprint
main = Blueprint('main', __name__)
from . import routes
# app/__init__.py
from flask import Flask
from app.main.routes import main
app = Flask(__name__)
app.register_blueprint(main)
12.3 环境变量 #
使用环境变量存储敏感信息,避免硬编码。
12.4 测试 #
安装测试工具:
bash
pip install pytest coverage
创建测试用例:
python
import pytest
from app import create_app, db
from app.models import User
@pytest.fixture
def client():
app = create_app()
app.config['TESTING'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
with app.app_context():
db.create_all()
yield app.test_client()
db.drop_all()
def test_home_page(client):
response = client.get('/')
assert response.status_code == 200
assert b'Welcome' in response.data
运行测试:
bash
pytest
coverage run -m pytest
coverage report
12.5 性能优化 #
- 使用缓存(如Flask-Caching)
- 数据库查询优化
- 静态文件压缩
- 使用异步任务(如Celery)
十三、常用扩展 #
| 扩展名称 | 用途 | 安装命令 |
|---|---|---|
| Flask-WTF | 表单处理 | pip install flask-wtf |
| Flask-SQLAlchemy | 数据库集成 | pip install flask-sqlalchemy |
| Flask-Login | 用户认证 | pip install flask-login |
| Flask-Mail | 邮件发送 | pip install flask-mail |
| Flask-Bcrypt | 密码哈希 | pip install flask-bcrypt |
| Flask-Caching | 缓存支持 | pip install flask-caching |
| Flask-RESTful | REST API开发 | pip install flask-restful |
| Flask-Admin | 管理界面 | pip install flask-admin |
| Flask-Migrate | 数据库迁移 | pip install flask-migrate |
| Flask-SocketIO | WebSocket支持 | pip install flask-socketio |
十四、总结 #
Flask是一个灵活且强大的Python Web框架,适合从简单的个人项目到复杂的企业应用。通过掌握本文介绍的基础概念、核心功能和最佳实践,您将能够构建高质量的Flask应用程序。
继续学习和探索Flask生态系统,您将发现更多高级功能和扩展,帮助您更高效地开发Web应用。
最后更新:2026-02-07