1. 为什么选择Flask构建轻量级Web应用
十年前我刚入行时,第一次接触Python Web开发就被Flask的简洁性震撼到了。当时需要快速搭建一个内部数据看板,从安装到第一个页面呈现只用了15分钟。这种"微框架"(Microframework)的设计哲学,让开发者能够用最少的样板代码启动项目,特别适合中小型应用开发。
Flask的核心优势在于其可扩展性。就像乐高积木一样,你可以从最简单的单文件应用开始,然后按需添加数据库支持(SQLAlchemy)、用户认证(Flask-Login)、后台任务(Celery)等组件。这种"按需取用"的特性,使得Flask在快速原型开发和小型项目部署中具有独特优势。
重要提示:虽然Flask以轻量著称,但通过合理的扩展组合,它完全可以支撑日PV百万级的生产环境。我经手的一个电商促销系统就是用纯Flask构建的,在618期间稳定处理了峰值QPS 3000+的请求。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开发环境准备与基础配置
2.1 Python环境配置建议
我强烈推荐使用pyenv管理Python版本,特别是需要同时维护多个项目时。以下是经过验证的稳定组合:
bash复制# 安装Python 3.8.12(LTS版本)
pyenv install 3.8.12
# 创建虚拟环境
python -m venv venv
# 激活环境
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
对于包管理,不要直接pip install,而是先创建requirements.txt:
code复制Flask==2.0.3
Werkzeug==2.0.3
然后使用pip install -r requirements.txt安装。这种做法的好处是:
- 明确记录依赖版本
- 方便团队协作和环境重建
- 避免依赖冲突
2.2 最小化Flask应用结构
一个规范的Flask项目应该有这样的目录结构(即使再简单的项目也建议遵守):
code复制/project-root
│── /venv # 虚拟环境目录
│── /static # 静态文件(CSS/JS/图片)
│── /templates # Jinja2模板
│── app.py # 主应用文件
│── config.py # 配置参数
│── requirements.txt # 依赖清单
典型的app.py内容:
python复制from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "<h1>Hello World!</h1>"
if __name__ == '__main__':
app.run(debug=True)
启动应用后,访问http://localhost:5000就能看到结果。注意生产环境绝对不要使用debug=True模式!
3. 核心功能开发实战
3.1 路由系统的进阶用法
Flask的路由系统远比表面看起来强大。这是我总结的几个实用技巧:
动态URL参数处理:
python复制@app.route('/user/<username>')
def show_user(username):
# 自动将URL中的username传入函数
return f"User: {username}"
# 指定参数类型
@app.route('/post/<int:post_id>')
def show_post(post_id):
# post_id自动转为整数
return f"Post ID: {post_id}"
HTTP方法区分:
python复制from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return do_login(request.form)
else:
return show_login_form()
蓝图(Blueprint)组织大型项目:
python复制# 在auth/views.py中
from flask import Blueprint
bp = Blueprint('auth', __name__)
@bp.route('/login')
def login():
return "Login Page"
# 在主app.py中注册
from auth.views import bp as auth_bp
app.register_blueprint(auth_bp, url_prefix='/auth')
3.2 模板引擎深度使用
Flask默认使用Jinja2模板引擎,支持这些高级特性:
模板继承:
base.html:
html复制<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
home.html:
html复制{% extends "base.html" %}
{% block title %}Home Page{% endblock %}
{% block content %}
<h1>Welcome!</h1>
{% endblock %}
宏定义(类似函数):
html复制{% macro render_comment(comment) %}
<div class="comment">
<p>{{ comment.text }}</p>
<small>By {{ comment.author }}</small>
</div>
{% endmacro %}
{# 调用宏 #}
{{ render_comment(comment) }}
自定义过滤器:
python复制# 注册过滤器
@app.template_filter('reverse')
def reverse_filter(s):
return s[::-1]
# 模板中使用
{{ "hello"|reverse }} # 输出 "olleh"
4. 数据持久化方案选型
4.1 SQLite快速入门
对于小型应用,SQLite是最方便的起步选择:
python复制import sqlite3
from flask import g
def get_db():
if 'db' not in g:
g.db = sqlite3.connect('database.db')
g.db.row_factory = sqlite3.Row # 使返回字典形式
return g.db
@app.teardown_appcontext
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
基本CRUD操作:
python复制# 创建表
db.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
)
""")
db.commit()
# 插入数据
db.execute(
"INSERT INTO users (username, password) VALUES (?, ?)",
(username, generate_password_hash(password))
)
db.commit()
# 查询数据
user = db.execute(
"SELECT * FROM users WHERE username = ?",
(username,)
).fetchone()
4.2 SQLAlchemy ORM进阶
对于更复杂的项目,推荐使用Flask-SQLAlchemy:
python复制from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return f'<User {self.username}>'
常用操作示例:
python复制# 创建表
db.create_all()
# 添加用户
new_user = User(username='admin', email='admin@example.com')
db.session.add(new_user)
db.session.commit()
# 查询
user = User.query.filter_by(username='admin').first()
# 分页查询
users = User.query.paginate(page=2, per_page=10)
5. 用户认证与安全实践
5.1 密码安全存储
绝对不要明文存储密码!使用Werkzeug的安全工具:
python复制from werkzeug.security import generate_password_hash, check_password_hash
# 注册时
hashed_pw = generate_password_hash('mypassword')
# 验证时
if check_password_hash(hashed_pw, 'inputpassword'):
print("Password correct")
5.2 Flask-Login集成
实现用户会话管理的最佳实践:
python复制from flask_login import LoginManager, UserMixin, login_user
login_manager = LoginManager(app)
class User(UserMixin, db.Model):
# 继承UserMixin获得默认实现
pass
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# 登录视图
@app.route('/login', methods=['POST'])
def login():
user = User.query.filter_by(username=request.form['username']).first()
if user and check_password_hash(user.password, request.form['password']):
login_user(user)
return redirect(url_for('dashboard'))
保护路由:
python复制from flask_login import login_required
@app.route('/settings')
@login_required
def settings():
return "Private Settings Page"
6. 生产环境部署要点
6.1 WSGI服务器选择
开发服务器(app.run)绝对不能用于生产!推荐选择:
-
Gunicorn (适合中小型应用)
bash复制
pip install gunicorn gunicorn -w 4 -b :8000 app:app -
uWSGI (高性能,配置复杂)
ini复制[uwsgi] module = app:app master = true processes = 5 socket = :8000
6.2 Nginx反向代理配置
典型配置示例:
nginx复制server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /static {
alias /path/to/your/static/files;
expires 30d;
}
}
6.3 配置管理最佳实践
使用类继承管理不同环境配置:
python复制class Config:
SECRET_KEY = os.getenv('SECRET_KEY')
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///dev.db'
class ProductionConfig(Config):
DEBUG = False
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')
config = {
'development': DevelopmentConfig,
'production': ProductionConfig
}
在app工厂中加载配置:
python复制def create_app(config_name='development'):
app = Flask(__name__)
app.config.from_object(config[config_name])
# 初始化扩展...
return app
7. 性能优化技巧
7.1 数据库查询优化
常见性能陷阱及解决方案:
-
N+1查询问题:
python复制# 错误做法 - 每次循环都查询数据库 for user in User.query.all(): print(user.posts.all()) # 正确做法 - 使用joinedload from sqlalchemy.orm import joinedload users = User.query.options(joinedload(User.posts)).all() -
分页优化:
python复制# 不要用all()后再切片 users = User.query.paginate(page=1, per_page=20)
7.2 缓存策略实现
使用Flask-Caching扩展:
python复制from flask_caching import Cache
cache = Cache(config={'CACHE_TYPE': 'SimpleCache'})
cache.init_app(app)
@app.route('/expensive-query')
@cache.cached(timeout=300) # 缓存5分钟
def expensive_query():
results = do_expensive_calculation()
return jsonify(results)
对于动态内容,可以使用片段缓存:
html复制{% cache 300, 'sidebar' %}
<div class="sidebar">
{{ render_sidebar() }}
</div>
{% endcache %}
8. 常见问题排查指南
8.1 典型错误解决方案
ImportError: cannot import name 'app' from 'app'
这通常是由于循环导入导致的。解决方案:
- 使用应用工厂模式
- 将扩展初始化移到单独的extensions.py
- 使用延迟导入
SQLAlchemy DetachedInstanceError
当尝试访问已过期(session已关闭)的对象属性时发生。解决方法:
python复制# 在查询时使用expire_on_commit=False
db.session.expire_on_commit = False
# 或者重新加载对象
db.session.refresh(user)
8.2 调试技巧
-
使用Flask-DebugToolbar:
python复制from flask_debugtoolbar import DebugToolbarExtension toolbar = DebugToolbarExtension(app) -
记录慢查询:
python复制@app.after_request def after_request(response): for query in get_debug_queries(): if query.duration >= 0.5: # 秒 app.logger.warning( f"Slow query: {query.statement}\n" f"Parameters: {query.parameters}\n" f"Duration: {query.duration}s\n" f"Context: {query.context}" ) return response -
在生产环境记录异常:
python复制@app.errorhandler(500) def internal_error(error): app.logger.error(f"500 Error: {error}") return render_template('500.html'), 500
9. 项目结构进阶建议
对于大型项目,推荐这样的结构:
code复制/project
│── /app
│ │── /static
│ │── /templates
│ │── /auth
│ │ │── routes.py
│ │ │── models.py
│ │── /blog
│ │ │── routes.py
│ │ │── models.py
│ │── __init__.py # 应用工厂
│ │── extensions.py
│── /migrations
│── /tests
│── config.py
│── requirements.txt
│── manage.py # 命令行工具
关键改进点:
- 按功能模块组织代码(蓝图)
- 分离配置和扩展初始化
- 独立的测试目录
- 使用Flask-Migrate管理数据库迁移
10. 测试策略与实施
10.1 单元测试基础
使用pytest的典型测试结构:
python复制import pytest
from app import create_app
from app.models import User
@pytest.fixture
def app():
app = create_app('testing')
yield app
@pytest.fixture
def client(app):
return app.test_client()
def test_home_page(client):
response = client.get('/')
assert response.status_code == 200
assert b'Welcome' in response.data
def test_user_creation(app):
with app.app_context():
user = User(username='test', email='test@example.com')
db.session.add(user)
db.session.commit()
assert User.query.count() == 1
10.2 集成测试示例
测试认证流程:
python复制def test_login(client, app):
# 先注册测试用户
with app.app_context():
user = User(username='testuser', email='test@example.com')
user.password = generate_password_hash('testpass')
db.session.add(user)
db.session.commit()
# 测试登录失败
response = client.post('/login', data={
'username': 'testuser',
'password': 'wrongpass'
}, follow_redirects=True)
assert b'Invalid credentials' in response.data
# 测试登录成功
response = client.post('/login', data={
'username': 'testuser',
'password': 'testpass'
}, follow_redirects=True)
assert response.status_code == 200
assert b'Dashboard' in response.data
11. 现代化前端集成
11.1 RESTful API开发
使用Flask-RESTful扩展:
python复制from flask_restful import Api, Resource
api = Api(app)
class UserAPI(Resource):
def get(self, user_id):
user = User.query.get_or_404(user_id)
return {'username': user.username, 'email': user.email}
def put(self, user_id):
user = User.query.get_or_404(user_id)
data = request.get_json()
user.email = data.get('email', user.email)
db.session.commit()
return {'message': 'User updated'}
api.add_resource(UserAPI, '/api/users/<int:user_id>')
11.2 前后端分离实践
使用Flask-CORS处理跨域:
python复制from flask_cors import CORS
CORS(app, resources={
r"/api/*": {
"origins": ["https://frontend-domain.com"],
"methods": ["GET", "POST", "PUT", "DELETE"],
"allow_headers": ["Content-Type", "Authorization"]
}
})
JWT认证实现:
python复制from flask_jwt_extended import JWTManager, create_access_token
app.config['JWT_SECRET_KEY'] = 'super-secret'
jwt = JWTManager(app)
@app.route('/api/login', methods=['POST'])
def api_login():
username = request.json.get('username')
password = request.json.get('password')
user = User.query.filter_by(username=username).first()
if user and check_password_hash(user.password, password):
access_token = create_access_token(identity=username)
return {'access_token': access_token}
return {'error': 'Invalid credentials'}, 401
12. 微服务架构下的Flask
12.1 服务间通信
使用requests库调用其他服务:
python复制import requests
from flask import jsonify
@app.route('/aggregated-data')
def get_aggregated_data():
# 调用用户服务
users = requests.get('http://user-service/api/users').json()
# 调用订单服务
orders = requests.get(
'http://order-service/api/orders',
headers={'Authorization': request.headers.get('Authorization')}
).json()
return jsonify({
'users': users,
'orders': orders
})
12.2 异步任务处理
使用Celery处理后台任务:
python复制from celery import Celery
def make_celery(app):
celery = Celery(
app.import_name,
broker=app.config['CELERY_BROKER_URL']
)
celery.conf.update(app.config)
return celery
celery = make_celery(app)
@celery.task
def send_async_email(email_data):
# 发送邮件逻辑
pass
# 在视图中调用
@app.route('/send-email')
def send_email():
email_data = {...}
send_async_email.delay(email_data)
return "Email will be sent shortly"
13. 监控与日志管理
13.1 结构化日志配置
python复制import logging
from logging.handlers import RotatingFileHandler
# 文件日志(最大100MB,保留3个备份)
file_handler = RotatingFileHandler(
'app.log', maxBytes=1024*1024*100, backupCount=3
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
# 控制台日志
if app.debug:
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
app.logger.addHandler(stream_handler)
13.2 Prometheus监控集成
使用Prometheus Flask Exporter:
python复制from prometheus_flask_exporter import PrometheusMetrics
metrics = PrometheusMetrics(app)
# 自定义指标
users_total = metrics.info(
'users_total', 'Total number of users'
)
@app.route('/register')
def register():
# 业务逻辑...
users_total.inc()
return "Registered"
14. 持续集成与部署
14.1 GitHub Actions配置
基础测试工作流:
yaml复制name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:13
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov
- name: Run tests
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
run: |
pytest --cov=app tests/
14.2 Docker化部署
基础Dockerfile:
dockerfile复制FROM python:3.8-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV FLASK_APP=app.py
ENV FLASK_ENV=production
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
docker-compose.yml示例:
yaml复制version: '3'
services:
web:
build: .
ports:
- "5000:5000"
environment:
- DATABASE_URL=postgresql://dbuser:dbpass@db:5432/appdb
depends_on:
- db
db:
image: postgres:13
environment:
POSTGRES_USER: dbuser
POSTGRES_PASSWORD: dbpass
POSTGRES_DB: appdb
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
15. 项目脚手架工具
使用Cookiecutter生成标准项目结构:
bash复制pip install cookiecutter
cookiecutter https://github.com/cookiecutter-flask/cookiecutter-flask
回答交互式问题后,将生成包含以下内容的项目:
- 预配置的Flask应用工厂
- 蓝图组织架构
- 测试配置
- Docker支持
- CI/CD管道配置
16. 性能基准测试
使用Locust进行负载测试:
locustfile.py示例:
python复制from locust import HttpUser, task, between
class WebsiteUser(HttpUser):
wait_time = between(1, 5)
@task
def index(self):
self.client.get("/")
@task(3)
def load_post(self):
self.client.get("/post/1")
def on_start(self):
self.client.post("/login", json={
"username": "testuser",
"password": "secret"
})
运行测试:
bash复制locust -f locustfile.py
访问http://localhost:8089配置模拟用户数和生成速率。
17. 安全加固措施
17.1 常见漏洞防护
-
CSRF防护:
python复制from flask_wtf.csrf import CSRFProtect csrf = CSRFProtect(app) -
XSS防护:
- 始终使用Jinja2的自动转义
- 对用户输入进行严格过滤
-
SQL注入防护:
- 永远使用参数化查询
- 避免直接拼接SQL语句
17.2 安全头部设置
使用Flask-Talisman:
python复制from flask_talisman import Talisman
Talisman(
app,
force_https=True,
strict_transport_security=True,
session_cookie_secure=True,
content_security_policy={
'default-src': "'self'",
'script-src': ["'self'", 'cdn.example.com'],
'style-src': ["'self'", "'unsafe-inline'"]
}
)
18. 国际化与本地化
使用Flask-Babel实现多语言支持:
python复制from flask_babel import Babel, _
app.config['BABEL_DEFAULT_LOCALE'] = 'en'
babel = Babel(app)
@babel.localeselector
def get_locale():
return request.accept_languages.best_match(['en', 'zh'])
@app.route('/')
def home():
return _("Hello World!")
翻译文件(messages.po):
code复制msgid "Hello World!"
msgstr "你好世界!"
编译翻译:
bash复制pybabel compile -d translations
19. 实时功能扩展
使用Flask-SocketIO实现WebSocket:
python复制from flask_socketio import SocketIO, emit
socketio = SocketIO(app)
@socketio.on('connect')
def handle_connect():
print('Client connected')
@socketio.on('chat_message')
def handle_message(data):
emit('new_message', {'text': data['text']}, broadcast=True)
if __name__ == '__main__':
socketio.run(app)
前端代码示例:
javascript复制const socket = io();
socket.on('connect', () => {
console.log('Connected to server');
});
socket.on('new_message', (data) => {
console.log('New message:', data.text);
});
function sendMessage() {
socket.emit('chat_message', {
text: document.getElementById('message').value
});
}
20. 项目文档自动化
使用Sphinx生成文档:
- 安装并初始化:
bash复制pip install sphinx
sphinx-quickstart docs
- 配置conf.py:
python复制extensions = ['sphinx.ext.autodoc']
import os
import sys
sys.path.insert(0, os.path.abspath('../'))
- 编写API文档(.rst文件):
code复制.. automodule:: app.routes
:members:
- 生成HTML:
bash复制cd docs && make html
21. 第三方服务集成
21.1 邮件发送示例
使用Flask-Mail:
python复制from flask_mail import Mail, Message
mail = Mail(app)
@app.route('/send-email')
def send_email():
msg = Message(
"Hello",
sender="from@example.com",
recipients=["to@example.com"]
)
msg.body = "This is a test email"
mail.send(msg)
return "Email sent"
21.2 支付网关集成
以Stripe为例:
python复制import stripe
stripe.api_key = app.config['STRIPE_SECRET_KEY']
@app.route('/create-payment', methods=['POST'])
def create_payment():
try:
intent = stripe.PaymentIntent.create(
amount=1000, # 单位是分
currency='usd',
metadata={'user_id': '123'}
)
return jsonify(client_secret=intent.client_secret)
except Exception as e:
return jsonify(error=str(e)), 403
22. 机器学习模型集成
使用Flask部署Scikit-learn模型:
python复制import joblib
from flask import jsonify
model = joblib.load('model.pkl')
@app.route('/predict', methods=['POST'])
def predict():
data = request.get_json()
features = preprocess(data['features'])
prediction = model.predict([features])
return jsonify({'result': prediction[0]})
优化建议:
- 使用异步任务处理耗时预测
- 实现模型缓存和热更新
- 添加输入数据验证
23. 微前端架构集成
将Flask作为微前端后端:
python复制from flask import send_from_directory
@app.route('/assets/<path:filename>')
def serve_static(filename):
return send_from_directory('dist/assets', filename)
@app.route('/<path:path>')
def serve_app(path):
return send_from_directory('dist', 'index.html')
@app.route('/')
def serve_home():
return send_from_directory('dist', 'index.html')
配合现代前端框架(如Vue/React)的静态构建输出。
24. 无服务器部署方案
使用Zappa部署到AWS Lambda:
- 安装配置:
bash复制pip install zappa
zappa init
- 编辑zappa_settings.json:
json复制{
"dev": {
"app_function": "app.app",
"aws_region": "us-east-1",
"profile_name": "default",
"project_name": "myflaskapp",
"runtime": "python3.8",
"s3_bucket": "zappa-deploy-bucket"
}
}
- 部署:
bash复制zappa deploy dev
25. 性能监控与APM
使用Elastic APM:
python复制from elasticapm.contrib.flask import ElasticAPM
app.config['ELASTIC_APM'] = {
'SERVICE_NAME': 'flask-app',
'SECRET_TOKEN': '<token>',
'SERVER_URL': 'http://apm-server:8200'
}
apm = ElasticAPM(app)
监控内容包括:
- 请求响应时间
- SQL查询性能
- 异常追踪
- 事务分析
26. 灰度发布策略
实现基于Cookie的流量分配:
python复制@app.before_request
def before_request():
if request.cookies.get('beta') == 'true' \
or random.random() < 0.1: # 10%流量
request.environ['USE_NEW_VERSION'] = True
@app.route('/new-feature')
def new_feature():
if request.environ.get('USE_NEW_VERSION'):
return "New Version"
return "Old Version"
设置Cookie:
python复制@app.route('/opt-in-beta')
def opt_in_beta():
resp = make_response(redirect('/'))
resp.set_cookie('beta', 'true')
return resp
27. 多租户架构实现
使用SQLAlchemy事件实现租户隔离:
python复制from sqlalchemy import event
from sqlalchemy.orm import Session
@event.listens_for(Session, 'do_orm_execute')
def receive_do_orm_execute(execute_state):
if execute_state.is_select:
tenant_id = get_tenant_id() # 从请求上下文中获取
execute_state.statement = execute_state.statement.where(
Model.tenant_id == tenant_id
)
请求处理器:
python复制@app.before_request
def set_tenant():
tenant_id = request.headers.get('X-Tenant-ID')
g.tenant_id = tenant_id
28. 自动化测试进阶
使用Factory Boy创建测试数据:
python复制import factory
from app.models import User
class UserFactory(factory.Factory):
class Meta:
model = User
username = factory.Sequence(lambda n: f'user{n}')
email = factory.LazyAttribute(lambda obj: f'{obj.username}@example.com')
def test_user_creation():
user = UserFactory()
assert '@example.com' in user.email
API测试示例:
python复制def test_api_auth(client):
# 创建测试用户
user = UserFactory(password='testpass')
# 获取token
response = client.post('/api/login', json={
'username': user.username,
'password': 'testpass'
})
token = response.json['access_token']
# 使用token访问受保护端点
response = client.get(
'/api/protected',
headers={'Authorization': f'Bearer {token}'}
)
assert response.status_code == 200
29. 配置管理进阶
使用环境变量和类继承:
python复制class Config:
SECRET_KEY = os.getenv('SECRET_KEY')
SQLALCHEMY_TRACK_MODIFICATIONS = False
@classmethod
def init_app(cls, app):
pass
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///dev.db'
class DockerConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')
config = {
'development': DevelopmentConfig,
'docker': DockerConfig,
'default': DevelopmentConfig
}
工厂函数中使用:
python复制def create_app(config_name='default'):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
# 初始化扩展...
return app
30. 项目升级与维护
30.1 依赖更新策略
- 定期检查更新:
bash复制pip list --outdated
- 测试更新:
bash复制pip install -U package
pytest
- 使用依赖约束:
code复制Flask>=2.0.0,<3.0.0
Werkzeug>=2.0.0,<3.0.0
30.2 数据库迁移管理
使用Flask-Migrate:
bash复制flask db init # 初始化
flask db migrate -m "add user table" # 生成迁移脚本
flask db upgrade # 执行升级
回滚到指定版本:
bash复制flask db downgrade <revision>
31. 异常处理最佳实践
全局异常处理器:
python复制@app.errorhandler(404)
def not_found(error):
return render_template('404.html'), 404
@app.errorhandler(500)
def internal_error(error):
db.session.rollback()
return render_template('500.html'), 500
class ValidationError(Exception):
pass
@app.errorhandler(ValidationError)
def handle_validation_error(error):
response = jsonify({'error': str(error)})
response.status_code = 400
return response
业务代码中抛出异常:
python复制if not valid_input(request.json):
raise ValidationError('Invalid input data')
32. API文档自动化
使用Flask-Swagger-UI:
python复制from flask_swagger_ui import get_swaggerui_blueprint
SWAGGER_URL = '/api/docs'
API_URL = '/static/swagger.json'
swaggerui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={'app_name': "My API"}
)
app.register_blueprint(swaggerui_blueprint, url_prefix=SWAGGER_URL)
生成swagger.json:
python复制@app.route('/static/swagger.json')
def swagger():
return jsonify({
"openapi": "3.0.0",
"info": {
"title": "My API",
"version": "1.0"
},
"paths": {
"/users": {
"get": {
"summary": "Get all users",
"responses": {
"200": {
"description": "List of users"
}
}
}
}
}
})
33. 前端资产构建集成
使用Flask-Assets管理静态资源:
python复制from flask_assets import Environment, Bundle
assets = Environment(app)
js = Bundle(
'js/jquery.js',
'js/app.js',
filters='jsmin',
output='gen/packed.js'
)
css = Bundle(
'css/bootstrap.css',
'css/style.css',
filters='cssmin',
output='gen/packed.css'
)
assets.register('js_all', js)
assets.register('css_all', css)
模板中使用:
html复制{% assets "css_all" %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
{% assets "js_all" %}
<script src="{{ ASSET_URL }}"></script>
{% endassets %}
34. 地理空间功能实现
使用GeoAlchemy2处理空间数据:
python复制from geoalchemy2 import Geometry
from sqlalchemy import Column, Integer
class Location(db.Model):
id = db.Column(Integer, primary_key=True)
