1. Flask视图函数入门:为什么它是Web开发的核心?
刚接触Flask时,我最困惑的就是这个看似简单的视图函数(View Function)为何被反复强调。直到有次深夜调试一个表单提交问题才发现:Flask中90%的业务逻辑都写在视图函数里。它就像餐厅的后厨,虽然顾客看不到,但每一道菜(HTTP响应)都从这里诞生。
视图函数本质上是个Python函数,它接收Web请求并返回响应。这种设计让Flask比Django等全栈框架更灵活——你可以用纯Python代码处理业务逻辑,不需要记忆复杂的类继承体系。这也是为什么很多初创公司技术选型时会首选Flask:快速迭代时,一个@app.route装饰器加几行代码就能上线新功能。
关键认知:视图函数不只是"处理请求的函数",它是MVC模式中的Controller层,负责协调模型(数据)和视图(模板)的交互
2. 从零构建你的第一个视图函数
2.1 基础环境配置
先确保你的Python环境是3.7+版本(这是Flask 2.x的最低要求)。我强烈建议使用虚拟环境:
bash复制python -m venv flask_env
source flask_env/bin/activate # Linux/Mac
flask_env\Scripts\activate # Windows
安装Flask时别直接用pip install flask,生产环境需要固定版本:
bash复制pip install flask==2.3.2 werkzeug==2.3.7 # 同时安装兼容的Werkzeug版本
2.2 最小化Flask应用
创建app.py文件,写入以下代码:
python复制from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "<h1>Welcome to Flask!</h1>"
if __name__ == '__main__':
app.run(debug=True)
运行后访问http://localhost:5000,你会看到加粗的欢迎文字。这里发生了几个关键事件:
@app.route('/')将URL路径/映射到home()函数- 浏览器请求
/时,Flask调用home()并返回其输出 - 默认端口5000是Flask的开发服务器端口
2.3 路由装饰器深度解析
@app.route其实是个语法糖,它等价于:
python复制def home():
return "<h1>Welcome to Flask!</h1>"
app.add_url_rule('/', 'home', home)
装饰器支持多个重要参数:
python复制@app.route('/user/<username>', methods=['GET', 'POST'], endpoint='user_profile')
<username>:动态URL参数methods:限制允许的HTTP方法endpoint:给路由命名,用于url_for()反向解析
3. 视图函数进阶技巧
3.1 请求对象(request)的完全指南
Flask自动将HTTP请求封装在request对象中。常用属性包括:
| 属性 | 类型 | 示例 | 说明 |
|---|---|---|---|
method |
str | 'GET' | HTTP请求方法 |
args |
ImmutableMultiDict | URL查询参数 | |
form |
ImmutableMultiDict | POST表单数据 | |
files |
ImmutableMultiDict | 上传的文件 | |
json |
dict | JSON请求体 |
处理表单提交的典型场景:
python复制from flask import request
@app.route('/login', methods=['POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
# 验证逻辑...
3.2 响应(response)的精细化控制
视图函数可以返回多种类型的响应:
-
字符串:自动包装为200 OK的HTML响应
python复制return "Hello World" -
元组:(response, status_code, headers)
python复制return "Not Found", 404, {'X-Error': 'Not exists'} -
Response对象(最灵活的方式):
python复制from flask import make_response @app.route('/cookie') def set_cookie(): resp = make_response("Cookie set!") resp.set_cookie('user', 'admin', max_age=3600) return resp -
JSON响应(API开发常用):
python复制from flask import jsonify @app.route('/api/data') def get_data(): return jsonify({'status': 'success', 'data': [1, 2, 3]})
3.3 蓝图(Blueprint)组织大型项目
当路由超过20个时,就该使用蓝图了。假设我们有个电商项目:
code复制/project
/auth
__init__.py
routes.py # 认证相关视图
/product
__init__.py
routes.py # 商品相关视图
app.py # 主应用
auth/routes.py示例:
python复制from flask import Blueprint
bp = Blueprint('auth', __name__, url_prefix='/auth')
@bp.route('/login')
def login():
return "Login Page"
@bp.route('/logout')
def logout():
return "Logout Page"
在app.py中注册蓝图:
python复制from auth.routes import bp as auth_bp
from product.routes import bp as product_bp
app.register_blueprint(auth_bp)
app.register_blueprint(product_bp)
4. 生产环境实战经验
4.1 性能优化技巧
-
路由懒加载:
对于不常用的路由,可以动态导入:python复制@app.route('/report') def generate_report(): from .utils import report_generator # 运行时才导入 return report_generator.run() -
JSON响应加速:
替换默认的jsonify:python复制import orjson from flask import Response def json_response(data): return Response( orjson.dumps(data), mimetype='application/json' ) -
视图函数缓存:
使用functools.lru_cache缓存纯函数:python复制from functools import lru_cache @lru_cache(maxsize=32) @app.route('/expensive-calculation/<int:x>') def heavy_calc(x): result = x ** x # 非常耗时的计算 return str(result)
4.2 错误处理最佳实践
自定义错误处理器:
python复制@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
@app.errorhandler(500)
def internal_error(e):
db.session.rollback() # 重要:回滚失败的数据库会话
return render_template('500.html'), 500
API的错误响应标准化:
python复制class APIError(Exception):
status_code = 400
def __init__(self, message, status_code=None):
super().__init__()
self.message = message
if status_code is not None:
self.status_code = status_code
@app.errorhandler(APIError)
def handle_api_error(e):
return jsonify({
'error': e.message,
'code': e.status_code
}), e.status_code
4.3 视图函数单元测试
使用pytest测试视图函数:
python复制import pytest
from myapp import create_app
@pytest.fixture
def client():
app = create_app()
app.config['TESTING'] = True
with app.test_client() as client:
yield client
def test_home_page(client):
response = client.get('/')
assert response.status_code == 200
assert b'Welcome' in response.data
def test_login(client):
response = client.post('/login', data={
'username': 'test',
'password': 'secret'
}, follow_redirects=True)
assert response.request.path == '/dashboard'
5. 常见问题排坑指南
5.1 路由匹配的坑
问题1:动态路由参数总是字符串
python复制@app.route('/user/<id>')
def get_user(id):
# id永远是str类型,即使看起来像数字
if id.isdigit(): # 必须手动检查
id = int(id)
问题2:路由顺序影响匹配
python复制@app.route('/user/<name>') # 这个会拦截/admin
@app.route('/user/admin')
def user_page(name):
# 永远执行不到/user/admin
解决方案:明确定义更具体的路由在前
python复制@app.route('/user/admin') # 更具体的放前面
@app.route('/user/<name>')
5.2 请求上下文陷阱
问题:在视图函数外访问request报错:
code复制RuntimeError: Working outside of request context
解决方案:
- 确保代码在视图函数或带有
@app.route装饰器的函数内 - 需要外部访问时,使用请求上下文:
python复制from flask import current_app with current_app.test_request_context('/some-url'): print(request.url) # 现在可以访问
5.3 异步视图函数注意事项
Flask 2.0+支持async视图,但有限制:
python复制@app.route('/async')
async def async_view():
import asyncio
await asyncio.sleep(1)
return "Done"
注意:
- 需要ASGI服务器(如Hypercorn)才能发挥异步优势
- 同步扩展(如Flask-SQLAlchemy)在异步视图中会阻塞事件循环
- 简单IO操作使用异步可能反而更慢(线程池可能更高效)
6. 视图函数安全加固
6.1 输入验证必做项
-
必用Werkzeug的验证器:
python复制from werkzeug.security import check_password_hash from werkzeug.utils import secure_filename # 密码验证 if not check_password_hash(user.password_hash, input_password): abort(401) # 安全文件名 filename = secure_filename(request.files['file'].filename) -
参数类型强制转换:
python复制from flask import abort @app.route('/price/<float:price>') def show_price(price): if price <= 0: abort(400, description="Price must be positive") return f"Price: {price:.2f}"
6.2 CSRF防护实战
启用Flask-WTF的CSRF保护:
python复制from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)
# 表单模板中必须添加:
# <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
# API可以豁免(需配合其他验证)
@csrf.exempt
@app.route('/api', methods=['POST'])
def api_endpoint():
pass
6.3 速率限制实现
使用Flask-Limiter防止暴力破解:
python复制from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app=app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route('/login', methods=['POST'])
@limiter.limit("5 per minute")
def login():
# 登录逻辑
7. 视图函数与数据库交互
7.1 SQLAlchemy集成模式
典型CRUD操作示例:
python复制@app.route('/posts')
def list_posts():
page = request.args.get('page', 1, type=int)
posts = Post.query.paginate(page=page, per_page=10)
return render_template('posts.html', posts=posts)
@app.route('/post/<int:id>', methods=['DELETE'])
def delete_post(id):
post = Post.query.get_or_404(id)
db.session.delete(post)
db.session.commit()
return '', 204
7.2 事务管理要点
python复制@app.route('/transfer', methods=['POST'])
def transfer_money():
from_account = Account.query.get(request.form['from'])
to_account = Account.query.get(request.form['to'])
amount = decimal.Decimal(request.form['amount'])
try:
from_account.balance -= amount
to_account.balance += amount
db.session.commit()
return "Transfer successful"
except Exception as e:
db.session.rollback()
current_app.logger.error(f"Transfer failed: {str(e)}")
abort(500)
7.3 连接池优化配置
在生产环境中调整:
python复制app.config.update({
'SQLALCHEMY_POOL_SIZE': 20,
'SQLALCHEMY_MAX_OVERFLOW': 10,
'SQLALCHEMY_POOL_RECYCLE': 1800, # 30分钟回收连接
'SQLALCHEMY_POOL_TIMEOUT': 30
})
8. 微服务架构中的视图函数
8.1 RESTful API设计规范
好的API视图应该:
-
使用HTTP方法明确操作类型:
- GET /articles - 列表
- POST /articles - 创建
- GET /articles/1 - 详情
- PUT /articles/1 - 全量更新
- PATCH /articles/1 - 部分更新
- DELETE /articles/1 - 删除
-
版本控制通过URL或Header实现:
python复制@app.route('/api/v1/users') def list_users_v1(): pass -
错误响应标准化:
python复制@app.errorhandler(404) def not_found(e): return jsonify({ 'error': str(e), 'documentation_url': 'https://api.example.com/docs' }), 404
8.2 认证方案实现
JWT认证示例:
python复制from flask_jwt_extended import (
JWTManager, create_access_token,
jwt_required, get_jwt_identity
)
app.config['JWT_SECRET_KEY'] = 'super-secret'
jwt = JWTManager(app)
@app.route('/login', methods=['POST'])
def login():
username = request.json.get('username')
password = request.json.get('password')
# 验证逻辑...
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token)
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200
9. 视图函数调试技巧
9.1 交互式调试器使用
当debug=True时,Flask会在错误页面启动交互式调试器。但生产环境必须禁用它:
python复制app.run(debug=False) # 生产环境
安全替代方案:
python复制from werkzeug.debug import DebuggedApplication
app.wsgi_app = DebuggedApplication(app.wsgi_app, pin_security=True)
9.2 日志记录策略
结构化日志配置:
python复制import logging
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
'app.log', maxBytes=10000, backupCount=3
)
handler.setFormatter(logging.Formatter(
'[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
))
app.logger.addHandler(handler)
app.logger.setLevel(logging.INFO)
@app.route('/log-demo')
def log_demo():
app.logger.info('User accessed log demo')
try:
1 / 0
except Exception as e:
app.logger.error(f'Math error: {str(e)}', exc_info=True)
return "Check your logs"
9.3 性能分析工具
使用cProfile分析视图函数:
python复制import cProfile
import pstats
from io import StringIO
@app.route('/profile')
def profile_demo():
pr = cProfile.Profile()
pr.enable()
# 被分析的代码
result = some_expensive_operation()
pr.disable()
s = StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats('cumulative')
ps.print_stats()
return f"<pre>{s.getvalue()}</pre>"
10. 视图函数设计模式
10.1 基于类的视图(MethodView)
Flask的MethodView让RESTful路由更清晰:
python复制from flask.views import MethodView
class UserAPI(MethodView):
def get(self, user_id):
if user_id is None:
return jsonify(User.query.all())
return jsonify(User.query.get_or_404(user_id))
def post(self):
user = User(**request.json)
db.session.add(user)
db.session.commit()
return jsonify(user), 201
# 注册路由
user_view = UserAPI.as_view('user_api')
app.add_url_rule('/users/', defaults={'user_id': None},
view_func=user_view, methods=['GET'])
app.add_url_rule('/users/', view_func=user_view, methods=['POST'])
app.add_url_rule('/users/<int:user_id>', view_func=user_view,
methods=['GET', 'PUT', 'DELETE'])
10.2 装饰器组合技巧
创建需要登录和管理员权限的视图:
python复制from functools import wraps
def login_required(f):
@wraps(f)
def decorated(*args, **kwargs):
if not current_user.is_authenticated:
abort(401)
return f(*args, **kwargs)
return decorated
def admin_required(f):
@wraps(f)
def decorated(*args, **kwargs):
if not current_user.is_admin:
abort(403)
return f(*args, **kwargs)
return decorated
@app.route('/admin')
@login_required
@admin_required
def admin_panel():
return "Admin Dashboard"
10.3 插件化视图函数
将复杂逻辑拆分为插件:
python复制# extensions.py
class PaymentGateway:
def __init__(self, app=None):
if app is not None:
self.init_app(app)
def init_app(self, app):
app.extensions['payment'] = self
def process_payment(self, amount):
# 支付处理逻辑
return transaction_id
# app.py
payment = PaymentGateway()
payment.init_app(app)
@app.route('/checkout', methods=['POST'])
def checkout():
transaction_id = current_app.extensions['payment'].process_payment(100)
return jsonify(txid=transaction_id)
11. 视图函数与前端集成
11.1 模板渲染最佳实践
使用Jinja2模板时:
python复制@app.route('/dashboard')
def dashboard():
return render_template('dashboard.html',
user=current_user,
notifications=get_unread_count())
模板继承结构示例:
code复制templates/
base.html
layouts/
sidebar.html
partials/
header.html
pages/
dashboard.html
11.2 AJAX交互模式
处理前端AJAX请求:
python复制@app.route('/api/comments', methods=['POST'])
def add_comment():
if not request.is_json:
abort(415, description="Only JSON accepted")
data = request.get_json()
comment = Comment(text=data['text'])
db.session.add(comment)
db.session.commit()
return jsonify({
'id': comment.id,
'html': render_template('partials/comment.html', comment=comment)
})
11.3 实时通信方案
使用Socket.IO实现实时更新:
python复制from flask_socketio import SocketIO, emit
socketio = SocketIO(app)
@socketio.on('new_message')
def handle_message(data):
message = Message(text=data['text'])
db.session.add(message)
db.session.commit()
emit('message_added', {
'id': message.id,
'text': message.text
}, broadcast=True)
@app.route('/chat')
def chat_page():
return render_template('chat.html')
12. 部署优化策略
12.1 WSGI服务器选择
生产环境不要用app.run(),推荐配置:
bash复制# Gunicorn (适合纯Python应用)
gunicorn -w 4 -b :8000 app:app
# Waitress (跨平台)
waitress-serve --port=8000 app:app
# uWSGI (高性能)
uwsgi --http :8000 --wsgi-file app.py --callable app
12.2 静态文件处理
Nginx直接处理静态文件:
nginx复制location /static/ {
alias /path/to/your/static/files;
expires 30d;
access_log off;
}
Flask配置:
python复制app = Flask(__name__, static_url_path='',
static_folder='static',
template_folder='templates')
12.3 配置管理方案
使用环境变量+类继承模式:
python复制class Config:
SECRET_KEY = os.getenv('SECRET_KEY')
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_ECHO = True
class ProductionConfig(Config):
DEBUG = False
PREFERRED_URL_SCHEME = 'https'
app.config.from_object({
'development': DevelopmentConfig,
'production': ProductionConfig
}[os.getenv('FLASK_ENV', 'development')])
13. 视图函数监控与维护
13.1 健康检查端点
python复制@app.route('/health')
def health_check():
try:
db.session.execute('SELECT 1')
return jsonify({
'status': 'healthy',
'db': 'ok',
'timestamp': datetime.utcnow().isoformat()
})
except Exception as e:
return jsonify({
'status': 'unhealthy',
'error': str(e)
}), 500
13.2 性能指标暴露
使用Prometheus客户端:
python复制from prometheus_flask_exporter import PrometheusMetrics
metrics = PrometheusMetrics(app)
metrics.info('app_info', 'Application info', version='1.0')
@app.route('/metrics')
@metrics.do_not_track()
def metrics_endpoint():
return metrics.export()
13.3 请求追踪实现
python复制from flask import g
import uuid
@app.before_request
def start_trace():
g.request_id = str(uuid.uuid4())
g.start_time = time.time()
@app.after_request
def log_trace(response):
duration = (time.time() - g.start_time) * 1000
app.logger.info(
f"path={request.path} method={request.method} "
f"status={response.status_code} duration={duration:.2f}ms "
f"request_id={g.request_id}"
)
response.headers['X-Request-ID'] = g.request_id
return response
14. 视图函数扩展案例
14.1 文件上传服务
安全处理文件上传:
python复制import os
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/var/www/uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return 'No file part', 400
file = request.files['file']
if file.filename == '':
return 'No selected file', 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return 'File uploaded successfully', 201
return 'Invalid file type', 415
14.2 分页查询优化
高效分页方案:
python复制@app.route('/posts')
def list_posts():
page = request.args.get('page', 1, type=int)
per_page = min(request.args.get('per_page', 20, type=int), 100)
query = Post.query.order_by(Post.created_at.desc())
pagination = query.paginate(page=page, per_page=per_page)
return jsonify({
'items': [post.to_dict() for post in pagination.items],
'meta': {
'page': page,
'per_page': per_page,
'total_pages': pagination.pages,
'total_items': pagination.total
}
})
14.3 后台任务触发
使用Celery异步处理:
python复制from celery import Celery
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
@celery.task
def process_data(data):
# 耗时操作
return result
@app.route('/start-task', methods=['POST'])
def start_task():
data = request.get_json()
task = process_data.delay(data)
return jsonify({'task_id': task.id}), 202
@app.route('/task-status/<task_id>')
def task_status(task_id):
task = process_data.AsyncResult(task_id)
return jsonify({
'status': task.status,
'result': task.result if task.ready() else None
})
15. 视图函数性能调优
15.1 数据库查询优化
避免N+1查询问题:
python复制# 不好的写法
@app.route('/users')
def bad_users():
users = User.query.all()
return jsonify([{
'name': user.name,
'posts': [p.title for p in user.posts] # 每次循环都查询数据库
} for user in users])
# 优化写法
@app.route('/users-optimized')
def good_users():
users = User.query.options(db.joinedload(User.posts)).all()
return jsonify([{
'name': user.name,
'posts': [p.title for p in user.posts] # 预先加载
} for user in users])
15.2 缓存策略实施
使用Flask-Caching:
python复制from flask_caching import Cache
cache = Cache(config={'CACHE_TYPE': 'SimpleCache'})
cache.init_app(app)
@app.route('/expensive-route')
@cache.cached(timeout=300) # 缓存5分钟
def expensive_operation():
result = do_expensive_calculation()
return jsonify(result)
@app.route('/user/<username>')
@cache.memoize(300) # 根据参数缓存
def get_user_profile(username):
return jsonify(User.query.filter_by(username=username).first_or_404())
15.3 Gzip压缩启用
python复制from flask_compress import Compress
Compress(app)
# 或者手动实现
@app.after_request
def compress_response(response):
accept_encoding = request.headers.get('Accept-Encoding', '')
if 'gzip' not in accept_encoding.lower():
return response
response.direct_passthrough = False
if (response.status_code < 200 or
response.status_code >= 300 or
'Content-Encoding' in response.headers):
return response
response.data = gzip.compress(response.data)
response.headers['Content-Encoding'] = 'gzip'
response.headers['Content-Length'] = len(response.data)
return response
16. 视图函数安全加固进阶
16.1 输入消毒处理
使用Bleach清理HTML输入:
python复制import bleach
ALLOWED_TAGS = ['a', 'b', 'i', 'u', 'p', 'br']
ALLOWED_ATTRIBUTES = {'a': ['href', 'title']}
@app.route('/comment', methods=['POST'])
def add_comment():
clean_html = bleach.clean(
request.form['content'],
tags=ALLOWED_TAGS,
attributes=ALLOWED_ATTRIBUTES
)
comment = Comment(content=clean_html)
db.session.add(comment)
db.session.commit()
return "Comment added"
16.2 敏感操作审计
记录关键操作:
python复制@app.route('/delete-account', methods=['POST'])
@login_required
def delete_account():
app.logger.info(
f"User {current_user.id} deleting account from IP {request.remote_addr}"
)
db.session.delete(current_user)
db.session.commit()
return "Account deleted"
16.3 安全头设置
python复制@app.after_request
def set_security_headers(response):
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
response.headers['X-XSS-Protection'] = '1; mode=block'
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
response.headers['Content-Security-Policy'] = "default-src 'self'"
return response
17. 视图函数测试全覆盖
17.1 单元测试示例
python复制import unittest
from app import create_app, db
class ViewTestCase(unittest.TestCase):
def setUp(self):
self.app = create_app('testing')
self.client = self.app.test_client()
self.app_context = self.app.app_context()
self.app_context.push()
db.create_all()
def tearDown(self):
db.session.remove()
db.drop_all()
self.app_context.pop()
def test_home_page(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
self.assertIn(b'Welcome', response.data)
def test_login(self):
response = self.client.post('/login', data={
'username': 'test',
'password': 'secret'
}, follow_redirects=True)
self.assertEqual(response.status_code, 200)
self.assertIn(b'Dashboard', response.data)
17.2 集成测试策略
使用pytest-fixture:
python复制import pytest
from app import create_app, db
@pytest.fixture
def app():
app = create_app('testing')
with app.app_context():
db.create_all()
yield app
db.drop_all()
@pytest.fixture
def client(app):
return app.test_client()
def test_api_endpoint(client):
response = client.get('/api/data')
assert response.status_code == 200
assert response.json['status'] == 'success'
17.3 压力测试方法
使用Locust模拟高并发:
python复制# locustfile.py
from locust import HttpUser, task, between
class WebsiteUser(HttpUser):
wait_time = between(1, 5)
@task
def load_home(self):
self.client.get("/")
@task(3)
def load_api(self):
self.client.get("/api/data")
运行测试:
bash复制locust -f locustfile.py
18. 视图函数文档生成
18.1 OpenAPI/Swagger集成
使用Flask-RESTx:
python复制from flask_restx import Api, Resource
api = Api(app, version='1.0', title='Sample API')
@api.route('/hello')
class HelloWorld(Resource):
@api.doc('Get greeting')
def get(self):
"""返回欢迎信息"""
return {'hello': 'world'}
@api.route('/echo')
class Echo(Resource):
@api.doc(params={'text': '要回显的文本'})
def get(self):
"""回显输入参数"""
return {'echo': api.payload}
18.2 自动化文档生成
使用apidoc注释:
python复制@app.route('/complex-endpoint', methods=['POST'])
def complex_operation():
"""
@api {post} /complex-endpoint 复杂操作
@apiName ComplexOperation
@apiGroup Advanced
@apiParam {String} required_field 必填字段
@apiParam {Number} [optional_field] 可选字段
@apiSuccess {Boolean} success 是否成功
@apiSuccess {String} message 结果消息
@apiError (400) {String} error 错误描述
"""
if not request.json.get('required_field'):
return {'error': 'Missing required field'}, 400
return {'success': True, 'message': 'Operation completed'}
18.3 交互式文档部署
使用ReDoc渲染OpenAPI:
python复制from flask_swagger_ui import get_swaggerui_blueprint
SWAGGER_URL = '/docs'
API_URL = '/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)
@app.route('/swagger.json')
def swagger():
return jsonify({
"openapi": "3.0.0",
"info": {"title": "My API", "version": "1.0"},
"paths": {
"/hello": {
"get": {
"responses": {"200": {"description": "成功响应"}}
}
}
}
})
19. 视图函数国际化
19.1 多语言支持实现
使用Flask-Babel:
python复制from flask_babel import Babel, _
app.config['BABEL_DEFAULT_LOCALE'] = 'zh'
app.config['BABEL_TRANSLATION_DIRECTORIES'] = '../translations'
babel = Babel(app)
@babel.localeselector
def get_locale():
return request.accept_languages.best_match(['zh', 'en'])
@app.route('/greet')
def greet():
return _('Hello World') # 根据语言环境返回不同翻译
19.2 本地化时间处理
python复制from flask_babel import format_datetime
from datetime import datetime
@app.route('/now')
def current_time():
return format_datetime(datetime.now())
19.3 动态内容翻译
python复制@app.route('/product/<int:id>')
def product_detail(id):
product = Product.query.get_or_404(id)
return render_template('product.html',
name=_(product.name),
description=_(product.description))
20. 视图函数与微前端集成
20.1 模块联邦支持
python复制@app.route('/module-federation')
def module_federation():
return render_template('federation.html',
remotes={
'app1': 'http://localhost:3001/remoteEntry.js',
'app2': 'http://localhost:3002/remoteEntry.js'
})
# federation.html
"""
<script src="https://cdn.jsdelivr.net/npm/webpack@5/dist/webpack.min.js"></script>
<script>
const { ModuleFederationPlugin } = webpack.container;
// 配置模块联邦...
</script>
"""
20.2 服务端渲染(SSR)集成
python复制
