当前位置: 首页 > article >正文

【Flask】Explore-Flask:早期 Flask 生态的实用指南

开源项目:explore-flask/README.rst at master · rpicard/explore-flask (github.com)

一、Coding conventions

Summary

  • Try to follow the coding style conventions laid out in PEP 8.

  • Try to document your app with docstrings as defined in PEP 257.

def launch_rocket():"""Main launch sequence director.Locks seatbelts, initiates radio and fires engines."""# [...]
  • Use relative imports to import your app’s internal modules.

# myapp/views.py# An absolute import gives us the User model
from myapp.models import User# A relative import does the same thing
from .models import User

✅ 至今仍然适用的原则

1. 遵循 PEP 8 代码风格
  • 为什么有效
    PEP 8 仍是 Python 官方推荐的代码风格标准,确保代码一致性和可读性。

    • 例如:缩进用 4 空格、变量名用 snake_case、类名用 CamelCase

  • 现代工具支持

    • 自动格式化工具(如 blackautopep8)可强制遵循 PEP 8。

    • IDE(如 VS Code、PyCharm)内置 PEP 8 检查。

  • 注意
    PEP 8 是指南而非铁律,部分规则可灵活调整(如行长度默认 88/79 字符,但 black 强制 88)。

2. 使用 PEP 257 文档字符串(Docstrings)
  • 为什么有效

    • 文档字符串是 Python 生态的通用约定,IDE 和工具(如 Sphinx、pydoc)依赖它生成文档。

    • 类型注解(Type Hints)的普及(PEP 484)并未取代文档字符串,而是互补。

  • 推荐格式

    • Google 风格(简洁)或 NumPy 风格(详细),而非严格的 PEP 257 原始格式。

def calculate(a: int, b: int) -> int:"""Compute the sum of two integers.Args:a: First integer.b: Second integer.Returns:Sum of a and b."""return a + b
3. 相对导入(Relative Imports)的合理使用
  • 适用场景

    • 在 包内部模块互相引用 时,相对导入(from . import module)仍是最清晰的方式。

    • 避免硬编码包名,提高可移植性(如重构时包名变更不影响导入)。

  • 现代补充

    • 结合 __init__.py 和 pyproject.toml 定义包结构(PEP 621)。


⚠️ 需要调整或谨慎使用的原则

1. 相对导入的潜在问题
  • 问题场景

    • 在脚本直接运行(python script.py)时,相对导入可能失败(因 __package__ 未定义)。

    • 复杂的项目结构(如嵌套包)可能导致导入混乱。

  • 现代建议

    • 优先使用 绝对导入from mypackage import module)除非明确需要相对导入。

    • 将可执行脚本放在包外,或通过 python -m mypackage.module 运行。

2. PEP 8 的局部调整
  • 灵活性增强

    • 行长度black 等工具默认允许 88 字符(原 PEP 8 建议 79)。

    • 类型注解:PEP 8 已更新允许更灵活的类型注解换行(PEP 484+)。

  • 例外情况

    • 某些 API 设计(如 Django 的 models.ForeignKey)可能不符合 PEP 8 命名,但遵循框架惯例更重要。

3. 文档字符串的过度工程化
  • 旧问题
    PEP 257 的原始规范(如单行文档字符串的格式)可能过于严格。

  • 现代实践

    • 更注重 实用性(如 Google/NumPy 风格),而非机械遵循 PEP 257。

    • 工具(如 pydocstyle)可配置检查规则。


🔧 2023 年推荐的最佳实践

原则现代调整建议
PEP 8 风格用 black 自动格式化,局部例外可通过 # fmt: off 忽略。
文档字符串结合类型注解 + Google/NumPy 风格,用 mkdocs 或 Sphinx 生成文档。
相对导入仅在包内部使用;脚本和顶层模块用绝对导入。

总结:如何应用这些原则 today?

  1. 坚持核心规范

    • PEP 8 和文档字符串仍是 Python 开发的基石,但可通过工具自动化。

  2. 灵活调整细节

    • 行长度、导入方式等根据项目和团队需求调整。

  3. 结合现代工具链

    • 格式化:black + isort

    • 文档:mkdocs-material + pydocstyle

    • 导入:优先绝对导入,包内用相对导入。

这些原则的核心理念(可读性、一致性、可维护性)始终重要,但实现方式更智能高效了。

二、Environment

Summary

  • Use virtualenv to keep your application’s dependencies together.

  • Use virtualenvwrapper to keep your virtual environments together.

  • Keep track of dependencies with one or more text files.

  • Use a version control system. I recommend Git.

  • Use .gitignore to keep clutter and secrets out of version control.

  • Debug mode can give you information about problems in development.

  • The Flask-DebugToolbar extension will give you even more of that information.

✅ 至今仍然适用的原则

1. 使用虚拟环境隔离依赖(virtualenv)
  • 为什么有效
    Python 项目依赖冲突问题依然存在(尤其是不同项目需要同一库的不同版本时)。虚拟环境仍是官方推荐的依赖隔离方案。

  • 现代改进
    Python 3.3+ 内置了 venv 模块(python -m venv venv),但 virtualenv 仍更灵活(如支持旧版 Python)。

2. 使用版本控制系统(Git)
  • 为什么有效
    Git 已成为行业标准(尤其是配合 GitHub/GitLab),代码版本管理、协作、回滚等需求不变。

  • 现代补充
    可结合 pre-commit 等工具自动化代码检查。

3. 用 .gitignore 排除无关文件
  • 为什么有效
    避免提交编译文件(如 .pyc)、敏感信息(如 .env)、IDE 配置等仍是基本规范。

  • 现代扩展
    现在更推荐使用 环境变量(如 python-dotenv)或 专用配置管理工具(如 Vault)管理密钥,而非手动忽略文件。

4. 记录依赖清单(requirements.txt)
  • 为什么有效
    明确依赖是项目可复现的基础。

  • 现代改进

    • 推荐使用 pip-tools 或 poetry 管理依赖(自动处理子依赖版本冲突)。

    • 区分开发/生产依赖(如 requirements-dev.txt)。

5. 调试模式与工具(Flask-DebugToolbar)
  • 为什么有效
    Debug 模式和 DebugToolbar 仍是快速定位问题的有效工具。

  • 注意点
    需确保仅限开发环境使用(生产环境禁用!)。


⚠️ 需要调整或过时的原则

1. virtualenvwrapper 的必要性降低
  • 原因

    • 现代工具(如 poetrypipenv)已内置虚拟环境管理功能。

    • IDE(如 VS Code、PyCharm)直接支持虚拟环境切换,减少手动操作需求。

  • 建议
    新项目可优先尝试 poetry(依赖管理 + 虚拟环境一体化)。

2. 纯手动维护依赖文件(pip freeze)
  • 问题
    pip freeze 会导出所有依赖(包括间接依赖),导致文件臃肿且难以维护。

  • 替代方案

    • 使用 poetry 的 pyproject.toml 或 pipenv 的 Pipfile 显式声明依赖。

    • 仅锁定版本时生成 requirements.txt(如部署用)。

3. Flask-DebugToolbar 的局限性
  • 现代挑战

    • 对异步框架(如 FastAPI)支持有限。

    • 前端复杂应用可能需要更专业的调试工具(如浏览器 DevTools + 后端日志聚合)。

  • 替代方案
    结合 loggingSentry(错误追踪)、Postman(API 调试)等。


🔧 2023 年推荐的工具链升级

传统方式现代替代方案优势
virtualenv + pippoetry / pdm依赖解析、虚拟环境管理一体化
requirements.txtpyproject.toml (PEP 621)标准化依赖声明,支持元数据
Flask-DebugToolbarpdbpp + logging + Sentry更灵活的调试和错误监控

总结:如何应用这些原则 today?

  1. 仍要坚持

    • 隔离环境、版本控制、依赖记录、调试安全。

  2. 需要更新

    • 用 poetry 替代 virtualenvwrapper + 手动 pip

    • 敏感信息改用环境变量或专用服务管理。

  3. 扩展实践

    • 容器化(Docker)进一步隔离环境。

    • CI/CD 自动化测试和部署。

这些原则的核心思想(隔离性、可复现性、安全性)依然重要,只是工具更高效了。

三、Organizing your project

Summary

  • Using a single module for your application is good for quick projects.

  • Using a package for your application is good for projects with views, models, forms and other components.

config.py
requirements.txt
run.py
instance/config.py
yourapp/__init__.pyviews.pymodels.pyforms.pystatic/templates/
  • Blueprints are a great way to organize projects with several distinct components.

✅ 至今仍然适用的原则

1. 单模块适合小型项目
  • 适用场景

    • 快速原型、微服务或简单 API(如一个 app.py 包含路由和逻辑)。

    • 仍常见于教程、实验性代码或小型工具开发。

  • 现代补充

    • 即使单文件,也应遵循模块化设计(如分离路由、业务逻辑)。

    • 可搭配 Flask 2.0 的 async 支持提升简单应用的性能。

2. 包结构适合复杂项目
  • 为什么有效

    • 分层架构(如 models/views/services/)仍是中大型项目的标准实践。

    • 支持更好的可测试性和可维护性。

  • 现代改进

    • 结合 工厂模式(Factory Pattern)创建应用实例(通过 create_app() 函数)。

    • 使用 Flask-SQLAlchemy 或 Flask-Pydantic 等扩展规范组件交互。

3. 蓝图(Blueprints)组织多组件
  • 核心优势

    • 模块化路由:将不同功能(如用户认证、API 版本)拆分为独立蓝图。

    • 资源隔离:每个蓝图可拥有自己的模板、静态文件。

  • 现代实践

    • 在微服务架构中,蓝图仍用于单体应用内的功能分区。

    • 结合 Flask-RESTX 或 Flask-Smorest 构建结构化 API。


⚠️ 需要调整或谨慎使用的原则

1. 单模块的局限性
  • 问题场景

    • 随着项目增长,单文件难以维护(路由、模型、逻辑混杂)。

    • 缺乏明确的依赖管理,易导致代码臃肿。

  • 替代方案

    • 即使小型项目,也建议拆分为 app.py + extensions.py + config.py 等。

2. 纯包结构的冗余性
  • 旧问题
    传统包结构(如 myapp/__init__.py + myapp/views.py)可能导致过度分层。

  • 现代优化

    • 按功能垂直拆分(如 auth/blog/ 子包),而非按技术分层(models/views/)。

    • 使用 Dependency Injection 替代隐式导入(减少循环依赖)。

3. 蓝图的替代方案
  • 新兴趋势

    • FastAPI 的 APIRouter:类似蓝图但更轻量,适合纯 API 项目。

    • 微服务拆分:若组件独立性极强,可直接拆分为独立服务(而非蓝图)。

  • 注意
    蓝图仍适用于 Flask 单体应用,但需避免过度设计(如嵌套蓝图)。


🔧 2023 年推荐的项目组织方式

中型项目(包 + 蓝图)
myapp/
├── __init__.py     # create_app() 工厂函数
├── auth/           # 认证蓝图
│   ├── routes.py
│   └── models.py
├── blog/           # 博客蓝图
│   ├── routes.py
│   └── templates/
├── extensions.py   # 数据库、缓存等扩展
└── config.py

大型项目(按功能垂直拆分)

myapp/
├── core/           # 核心逻辑
├── api/            # API 蓝图(可进一步拆分为 v1/, v2/)
├── cli/            # 命令行工具
├── tests/          # 按功能匹配的测试结构
└── config/├── dev.py└── prod.py

总结:如何应用这些原则 today?

  1. 坚持核心思想

    • 简单项目用单文件,复杂项目用包+蓝图。

    • 模块化设计始终重要。

  2. 现代调整

    • 优先按功能(而非技术)划分代码。

    • 结合工厂模式和依赖注入提升灵活性。

  3. 评估替代方案

    • 纯 API 项目可考虑 FastAPI;

    • 超大型应用直接拆微服务。

Flask 的这些原则仍具指导意义,但需根据项目规模和团队需求灵活调整。

四、configuration

Summary

  • A simple app may only need one configuration file: config.py.

DEBUG = True # Turns on debugging features in Flask
BCRYPT_LOG_ROUNDS = 12 # Configuration for the Flask-Bcrypt extension
MAIL_FROM_EMAIL = "robert@example.com" # For use in application emails
# app.py or app/__init__.py
from flask import Flaskapp = Flask(__name__)
app.config.from_object('config')# Now we can access the configuration variables via app.config["VAR_NAME"].
  • Instance folders can help us hide secret configuration values.

config.py
requirements.txt
run.py
instance/config.py
yourapp/__init__.pymodels.pyviews.pytemplates/static/
# app.py or app/__init__.pyapp = Flask(__name__, instance_relative_config=True)
app.config.from_object('config')
app.config.from_pyfile('config.py')
  • Instance folders can be used to alter an application’s configuration for a specific environment.

  • We should use environment variables and app.config.from_envvar() for more complicated environment-based configurations.

1. 简单应用只需一个 config.py

✅ 仍有优势,但需谨慎使用

  • 适用场景

    • 快速原型开发、小型项目、个人工具。

    • 无需多环境部署或敏感信息的场景。

  • 优势

    • 简单直接,适合低复杂度项目。

  • 过时点

    • 硬编码敏感信息:现代开发中,直接写密码/API 密钥到文件是严重的安全反模式。

    • 环境适应性差:无法轻松切换开发/生产配置。

改进建议
即使小型项目,也应避免硬编码敏感信息,至少用 .env 文件 + python-dotenv


2. 使用 Instance Folders 隐藏敏感配置

⚠️ 部分过时,仍有特定用途

  • 适用场景

    • 传统 Flask 项目(非云原生部署)。

    • 需要本地开发与生产配置分离的简单场景。

  • 优势

    • 避免敏感配置提交到版本控制(如 instance/config.py 在 .gitignore 中)。

  • 过时点

    • 云原生兼容性差:现代部署(Docker/K8s)更依赖环境变量或 Secrets 管理。

    • 不够动态:需手动维护不同环境的实例文件夹,不符合自动化流程。

改进建议
云原生项目中,优先使用环境变量或 Secrets 管理工具(如 Vault、K8s Secrets)。


3. 使用环境变量 + app.config.from_envvar()

✅ 仍是黄金标准

  • 适用场景

    • 任何需要多环境(开发/测试/生产)支持的项目。

    • 云原生、容器化(Docker/K8s)或 Serverless 部署。

  • 优势

    • 安全性:敏感信息通过运行时注入,不暴露在代码中。

    • 灵活性:无需修改代码即可切换环境配置。

    • 符合 12-Factor App:被现代 DevOps 工具链(CI/CD)原生支持。

  • 注意事项

    • 需配合工具(如 python-dotenv)简化本地开发。

现代扩展
使用更高级的配置库(如 dynaconfpydantic-settings)支持多格式(YAML/JSON)和类型校验。


4. 混合配置策略的演进

✅ 推荐实践:分层配置
现代项目通常结合以下方式:

  1. 默认配置config.py 或 settings.toml(非敏感值)。

  2. 环境覆盖:通过环境变量或 .env 文件(开发环境)。

  3. 生产机密:通过云平台 Secrets 管理(如 AWS Secrets Manager)。

优势

  • 兼顾开发便利性与生产安全性。

  • 避免“过时”方案的硬编码问题。


总结:哪些原则已过时?

原则是否过时原因替代方案
单一 config.py部分过时硬编码不安全默认配置 + 环境变量覆盖
Instance Folders基本过时云原生兼容性差环境变量/Secrets
环境变量仍是主流符合现代实践无,可扩展工具链

现代最佳实践建议

  1. 简单项目.env + python-dotenv + config.py(仅非敏感配置)。

  2. 复杂项目:环境变量 + dynaconf/pydantic-settings + 云 Secrets 管理。

  3. 彻底弃用:硬编码敏感信息、依赖实例文件夹切换环境。

云原生时代,环境变量和集中式 Secrets 管理已成为事实标准,而传统方法仅适用于遗留项目或极简场景。

五、Advanced patterns for views and routing

Summary

  • The @login_required decorator from Flask-Login helps you limit views to authenticated users.

# app.pyfrom flask import render_template
from flask_login import login_required, current_user@app.route('/')
def index():return render_template("index.html")@app.route('/dashboard')
@login_required
def account():return render_template("account.html")
  • The Flask-Cache extension gives you a bunch of decorators to implement various methods of caching.

# app.pyfrom flask_cache import Cache
from flask import Flaskapp = Flask()# We'd normally include configuration settings in this call
cache = Cache(app)@app.route('/')
@cache.cached(timeout=60)
def index():[...] # Make a few database calls to get the information we needreturn render_template('index.html',latest_posts=latest_posts,recent_users=recent_users,recent_photos=recent_photos)
  • We can develop custom view decorators to help us organize our code and stick to DRY (Don’t Repeat Yourself) coding principles.

# myapp/util.pyfrom functools import wraps
from datetime import datetimefrom flask import flash, redirect, url_forfrom flask_login import current_userdef check_expired(func):@wraps(func)def decorated_function(*args, **kwargs):if datetime.utcnow() > current_user.account_expires:flash("Your account has expired. Update your billing info.")return redirect(url_for('account_billing'))return func(*args, **kwargs)return decorated_function
  • Custom URL converters can be a great way to implement creative features involving URL’s.

1. @login_required 装饰器(Flask-Login)

✅ 仍在广泛使用

  • 现状

    • Flask-Login 仍是 Flask 生态中最主流的身份验证库,@login_required 是限制未登录访问的标准方式

    • 配合现代前端(如 JWT、OAuth2)时,可能改用权限校验中间件(如 Flask-JWT-Extended),但传统 Session 登录场景仍依赖此装饰器。

  • 优势

    • 简单直观,适合服务端渲染(SSR)或混合应用。

  • 注意点

    • 若项目完全基于 API(如 React/Vue 前端),可能改用 JWT 的 @jwt_required(但逻辑类似)。


2. Flask-Cache 的缓存装饰器

⚠️ 已过时,被替代

  • 现状

    • Flask-Cache 官方已停止维护,其继任者是 Flask-Caching(支持更现代的缓存后端,如 Redis、Memcached)。

    • 装饰器(如 @cache.cached())仍在使用,但底层实现更高效。

  • 现代替代方案

    • 使用 Flask-Caching + Redis 实现分布式缓存。

    • 对于 API 项目,可能直接用 CDN 缓存 或 HTTP 缓存头(如 Cache-Control)。

关键变化
缓存逻辑从“代码装饰器”扩展到“基础设施层”(如 Redis、Nginx)。


3. 自定义视图装饰器(DRY 原则)

✅ 仍是核心实践

  • 现状

    • 自定义装饰器(如 @check_permissions@log_requests)仍是 Flask 中复用逻辑的推荐方式

    • 在微服务或复杂项目中,可能结合 中间件(Middleware) 或 蓝图(Blueprint)钩子 实现类似功能。

  • 优势

    • 保持代码简洁,符合 DRY 原则(例如统一处理权限、日志、限流)。

  • 注意点

    • 过度使用装饰器可能导致代码可读性下降(需权衡)。


4. 自定义 URL 转换器

✅ 仍有用,但需求减少

  • 现状

    • Flask 内置的 URL 转换器(如 intstring)已覆盖大部分场景,自定义转换器(如 @app.url_value_preprocessor需求减少

    • 现代 RESTful API 更依赖 标准化的 URL 设计(如 /users/<uuid:user_id>),而非复杂自定义规则。

  • 适用场景

    • 需要特殊路由逻辑(如动态子域名、Slug 校验)时仍有用武之地。

替代趋势
复杂路由逻辑可能移交到 API Gateway(如 Kong、Traefik)或前端路由(React/Vue Router)。


总结:哪些原则已过时?

原则是否过时原因现代替代方案
@login_required仍主流无更优替代兼容 JWT 时需调整
Flask-Cache 装饰器已过时项目废弃Flask-Caching + Redis
自定义装饰器仍推荐DRY 原则核心可结合中间件
自定义 URL 转换器边缘化需求减少标准化路由或 API Gateway

现代 Flask 开发建议

  1. 身份验证

    • 传统 SSR:Flask-Login + @login_required

    • 纯 API:Flask-JWT-Extended + @jwt_required

  2. 缓存

    • 使用 Flask-Caching + Redis,而非旧版 Flask-Cache

  3. 代码复用

    • 优先用装饰器,复杂场景可搭配 蓝图的 before_request 或 中间件

  4. 路由设计

    • 遵循 RESTful 规范,非必要不自定义 URL 转换器。

Flask 的轻量级哲学使其核心原则(如装饰器)依然有效,但工具链(如缓存、身份验证)需跟随生态演进。

六、Blueprints

Summary

  • A blueprint is a collection of views, templates, static files and other extensions that can be applied to an application.

  • Blueprints are a great way to organize your application.

  • In a divisional structure, each blueprint is a collection of views, templates and static files which constitute a particular section of your application.

facebook/__init__.pytemplates/layout.htmlhome/layout.htmlindex.htmlabout.htmlsignup.htmllogin.htmldashboard/layout.htmlnews_feed.htmlwelcome.htmlfind_friends.htmlprofile/layout.htmltimeline.htmlabout.htmlphotos.htmlfriends.htmledit.htmlsettings/layout.htmlprivacy.htmlsecurity.htmlgeneral.htmlviews/__init__.pyhome.pydashboard.pyprofile.pysettings.pystatic/style.csslogo.pngmodels.py
  • In a functional structure, each blueprint is just a collection of views. The templates are all kept together, as are the static files.

  • To use a blueprint, you define it then register it on the application by calling Flask.register_blueprint()..

# facebook/__init__.pyfrom flask import Flask
from .views.profile import profileapp = Flask(__name__)
app.register_blueprint(profile)
  • You can define a dynamic URL prefix that will be applied to all routes in a blueprint.

# facebook/views/profile.pyfrom flask import Blueprint, render_templateprofile = Blueprint('profile', __name__, url_prefix='/<user_url_slug>')# [...]
# facebook/__init__.pyfrom flask import Flask
from .views.profile import profileapp = Flask(__name__)
app.register_blueprint(profile, url_prefix='/<user_url_slug>')
  • You can also define a dynamic subdomain for all routes in a blueprint.

  • Refactoring a growing application to use blueprints can be done in five relatively small steps.

1. 蓝图(Blueprint)作为应用组件集合

✅ 仍是核心模式

  • 现状

    • 蓝图仍然是 Flask 中模块化组织代码的标准方式,包含视图、模板、静态文件等。

    • 在微服务架构中,大型应用可能拆分为多个独立服务,但单体应用内仍依赖蓝图分模块。

  • 优势

    • 解耦功能模块(如 auth_bpadmin_bp),支持多人协作开发。

  • 现代调整

    • 结合 工厂模式(Application Factory) 动态注册蓝图,更适合测试和扩展。


2. 组织方式:功能型(Functional) vs 分区型(Divisional)

⚠️ 分区型(Divisional)更主流,功能型(Functional)边缘化

  • 分区型(Divisional)

    • 仍广泛使用:每个蓝图是一个完整功能模块(如 users_bp 包含视图、模板、静态文件)。

    • 适合大多数项目,符合“高内聚低耦合”原则。

  • 功能型(Functional)

    • 基本过时:将模板/静态文件全局集中管理,视图按逻辑拆分(如 auth_views_bpprofile_views_bp)。

    • 缺点:模板和静态文件难以维护,不符合组件化趋势。

现代实践
优先用分区型,甚至进一步拆分为 独立 Python 包(如 flask-admin 的插件化设计)。


3. 动态 URL 前缀/子域名

✅ 仍在使用,但需求减少

  • 动态 URL 前缀url_prefix):

    • 常用:如 API 版本控制(/api/v1/)或多租户路径隔离(/tenant/<id>/)。

  • 动态子域名subdomain):

    • 边缘化:现代架构中,子域名路由通常由 反向代理(Nginx) 或 API Gateway(如 Kong)处理,而非应用层。

适用场景
简单项目可直接用 Flask 子域名功能,复杂场景移交基础设施层。


4. 重构为蓝图的步骤

✅ 仍是标准流程

  • 现状

    • 将大型应用拆分为蓝图的步骤(如逐步迁移视图、模板)未过时,但现代项目更倾向于 从一开始设计蓝图

  • 现代改进

    • 结合 模块化工厂模式create_app())动态注册蓝图,支持环境差异化配置。


5. 蓝图的注册方式(register_blueprint

✅ 语法未变,但注册时机演进

  • 传统方式

    • 直接在模块层调用 app.register_blueprint()

  • 现代方式

    • 在 应用工厂 中注册,或通过 插件系统(如 flask-sqlalchemy 的 init_app() 模式)延迟绑定。


总结:哪些原则已过时?

原则是否过时原因现代替代方案
蓝图作为模块化单元仍主流无可替代
功能型(Functional)结构已过时维护性差分区型(Divisional)
动态子域名边缘化由基础设施处理Nginx/API Gateway
直接全局注册蓝图不推荐缺乏灵活性应用工厂模式

现代 Flask 蓝图最佳实践

  1. 设计阶段

    • 按 业务边界 划分蓝图(如 auth_bporder_bp),每个蓝图包含自己的视图、模板、静态文件。

  2. 代码结构

    /app
    ├── /auth               # 蓝图模块
    │   ├── __init__.py     # 创建蓝图对象
    │   ├── routes.py       # 视图
    │   ├── templates/      # 蓝图专属模板
    │   └── static/         # 蓝图专属静态文件
    ├── /orders
    │   └── ...             # 同上
    └── create_app.py       # 应用工厂
  3. 注册时机

  • 在 create_app() 中动态注册蓝图,支持测试和配置隔离:

def create_app(config):app = Flask(__name__)app.register_blueprint(auth_bp)app.register_blueprint(orders_bp, url_prefix='/orders')return app
  1. 进阶场景

    • 将蓝图发布为 独立 PyPI 包(如 flask-admin),通过 pip 安装复用。


何时不需要蓝图?

  • 极简应用:单文件 Flask 应用(如原型开发)。

  • 微服务架构:功能已拆分为独立服务,单体内部无需再分蓝图。

Flask 蓝图的核心思想(模块化)并未过时,但实现细节需结合现代架构(如工厂模式、基础设施分层)优化。

七、Templates

Summary

  • Use Jinja for templating.

  • Jinja has two kinds of delimeters: {% ... %} and {{ ... }}. The first one is used to execute statements such as for-loops or assign values, the latter prints the result of the contained expression to the template.

{# _myapp/templates/layout.html_ #}<!DOCTYPE html>
<html lang="en"><head><title>{% block title %}{% endblock %}</title></head><body>{% block body %}<h1>This heading is defined in the parent.</h1>{% endblock %}</body>
</html>
  • Templates should go in myapp/templates/ — i.e. a directory inside of the application package.

  • I recommend that the structure of the templates/ directory mirror the URL structure of the app.

  • You should have a top-level layout.html in myapp/templates as well as one for each section of the site. The latter extend the former.

templates/layout.htmlindex.htmlabout.htmlprofile/layout.htmlindex.htmlphotos.htmladmin/layout.htmlindex.htmlanalytics.html
  • Macros are like functions made-up of template code.

{# myapp/templates/layout.html #}{% from "macros.html" import nav_link with context %}
<!DOCTYPE html>
<html lang="en"><head>{% block head %}<title>My application</title>{% endblock %}</head><body><ul class="nav-list">{{ nav_link('home', 'Home') }}{{ nav_link('about', 'About') }}{{ nav_link('contact', 'Get in touch') }}</ul>{% block body %}{% endblock %}</body>
</html>
  • Filters are functions made-up of Python code and used in templates.

1. 使用 Jinja2 作为模板引擎

✅ 仍是 Flask 的黄金标准

  • 现状

    • Jinja2 仍是 Flask 默认且官方推荐的模板引擎,与 Flask 深度集成。

    • 现代前端框架(如 React/Vue)的兴起减少了服务端渲染(SSR)的使用,但 Jinja2 在 SSR 场景中不可替代

  • 优势

    • 语法简洁,支持模板继承、宏等高级功能。

    • 适合内容型网站(如博客、CMS)或需要 SEO 的页面。

  • 注意点

    • 纯 API 项目可能完全不需要 Jinja2。


2. Jinja2 分隔符 {% ... %} 和 {{ ... }}

✅ 语法未变,仍是核心

  • 现代调整

    • 新增 {% ... %} 的扩展用法(如 {% set x = namespace() %}),但基础逻辑不变。

    • 前端开发者可能更熟悉 JSX/Vue 的 {{ }},但 Jinja2 的语义保持一致。


3. 模板目录应位于 myapp/templates/

⚠️ 仍适用,但灵活性增加

  • 传统实践

    • Flask 默认从 templates/ 加载模板,符合“约定优于配置”原则。

  • 现代演进

    • 可通过 template_folder 参数自定义路径(如 Flask(__name__, template_folder="../frontend/templates"))。

    • 大型项目可能将模板拆分为 独立包(如共享模板库)。

建议:除非有特殊需求,否则仍推荐默认目录结构。


4. 模板目录结构应镜像 URL 结构

❌ 已过时(仅适用于简单项目)

  • 过时原因

    • 现代项目更倾向于 按功能模块组织模板(如 templates/auth/login.html),而非严格匹配 URL(如 /auth/login)。

    • RESTful API 和前端框架的普及使得 URL 结构与模板解耦。

  • 例外

    • 内容型网站(如新闻分类)可能仍保留部分镜像结构。


5. 顶层 layout.html + 区块模板继承

✅ 仍是最佳实践

  • 现状

    • 基模板(layout.html)定义通用结构(如导航栏、页脚),子模板通过 {% extends %} 和 {% block %} 覆盖特定区块。

    • 与前端框架的“组件化”思想一致(如 Vue 的 <slot>)。

  • 优势

    • 避免重复代码,符合 DRY 原则。


6. 宏(Macros)作为模板函数

✅ 仍有用,但使用减少

  • 现状

    • 宏适合复用模板片段(如渲染表单字段),但在以下场景中被替代:

      • 前端框架(如 React/Vue)通过组件化实现更强大的复用。

      • 复杂逻辑更适合移回后端(通过 API 返回结构化数据)。

  • 适用场景

    • 服务端渲染中需要重复使用的 UI 元素(如分页控件)。


7. 过滤器(Filters)

✅ 仍有用,但需谨慎使用

  • 现状

    • 内置过滤器(如 |safe|capitalize)仍常用。

    • 自定义过滤器适合简单文本处理(如日期格式化),但复杂逻辑应优先在 后端处理 或通过 前端工具库(如 day.js)。

  • 风险

    • 过度使用过滤器会导致模板臃肿,违背“逻辑与表现分离”原则。


总结:哪些原则已过时?

原则是否过时原因现代替代方案
使用 Jinja2仍主流无更优替代纯 API 项目可省略
分隔符语法未变语法稳定
默认 templates/ 目录仍适用约定优于配置支持自定义路径
模板镜像 URL 结构已过时灵活性差按功能模块组织
模板继承(layout.html仍最佳实践DRY 原则类似前端组件化
宏(Macros)边缘化前端框架替代Vue/React 组件
过滤器(Filters)有限使用逻辑应后移后端处理或前端工具库

现代 Jinja2 模板开发建议

  1. 组织方式

    • 按功能模块划分模板目录(如 templates/auth/templates/blog/),而非机械匹配 URL。

  2. 逻辑分离

    • 复杂计算通过 视图函数 预处理,模板仅负责渲染。

  3. 组件化

    • 使用 {% include %} 或宏封装可复用 UI 片段(如按钮、卡片)。

  4. 安全性

    • 始终用 |safe 标记可信的 HTML 内容,避免 XSS。

  5. 结合现代工具

    • 开发阶段启用 TEMPLATES_AUTO_RELOAD=True 自动刷新模板。

何时不用 Jinja2?

  • 纯 API 项目(无服务端渲染)。

  • 前后端完全分离(前端使用 React/Vue)。

Jinja2 的核心功能(模板继承、变量渲染)依然不可替代,但需根据项目架构调整使用方式。

八、Static files

Summary

  • Static files go in the static/ directory.

myapp/__init__.pystatic/templates/views/models.py
run.py
  • Separate third-party libraries from your own static files.

static/css/lib/bootstrap.cssstyle.csshome.cssadmin.cssjs/lib/jquery.jshome.jsadmin.jsimg/logo.svgfavicon.ico
  • Specify the location of your favicon in your templates.

  • Use Flask-Assets to insert static files in your templates.

# myapp/util/assets.pyfrom flask_assets import Bundle, Environment
from .. import appbundles = {'home_js': Bundle('js/lib/jquery-1.10.2.js','js/home.js',output='gen/home.js'),'home_css': Bundle('css/lib/reset.css','css/common.css','css/home.css',output='gen/home.css'),'admin_js': Bundle('js/lib/jquery-1.10.2.js','js/lib/Chart.js','js/admin.js',output='gen/admin.js'),'admin_css': Bundle('css/lib/reset.css','css/common.css','css/admin.css',output='gen/admin.css')
}assets = Environment(app)assets.register(bundles)
  • Flask-Assets can compile, combine and compress your static files.

仍然适用的原则 ✅

  1. Static files go in the static/ directory

    • Flask 仍然默认使用 static/ 目录存放静态文件,这是官方推荐的做法

  2. Separate third-party libraries from your own static files

    • 仍然建议将第三方库(如 jQuery、Bootstrap)和自己的静态文件分开管理

  3. Specify the location of your favicon in your templates

    • 仍然需要在模板中正确指定 favicon 路径

部分过时/有更好替代方案的原则 ⚠️

  1. Use Flask-Assets to insert static files in your templates

    • 仍然可用但不是主流选择,现代前端工作流更倾向于使用:

      • Webpack/Vite 等现代打包工具

      • Flask 原生 url_for('static', ...) 方式

      • CDN 直接引入前端库

  2. Flask-Assets can compile, combine and compress your static files

    • 功能仍然存在但不再是首选方案,现代替代方案包括:

      • 使用 npm/yarn/pnpm + Webpack/Vite/Rollup

      • 使用 Flask-Minify 等专门压缩扩展

      • 云服务(如 AWS CloudFront)自动压缩

现代补充建议 ✨

  • 考虑使用 flask-static-compress 或 flask-minify 进行压缩

  • 对于复杂项目,建议采用前后端分离架构

  • 静态文件建议通过 CDN 分发

  • 现代前端框架(React/Vue)通常有自己的静态文件处理方式

Flask-Assets 虽然仍能工作,但在 2023 年后的新项目中已经很少被用作主要解决方案,除非是在维护传统项目。

九、Storing data

Summary

  • Use SQLAlchemy to work with relational databases.

# ourapp/__init__.pyfrom flask import Flask
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__, instance_relative_config=True)app.config.from_object('config')
app.config.from_pyfile('config.py')db = SQLAlchemy(app)
# ourapp/models.pyfrom . import dbclass Engine(db.Model):# Columnsid = db.Column(db.Integer, primary_key=True, autoincrement=True)title = db.Column(db.String(128))thrust = db.Column(db.Integer, default=0)
  • Use Flask-SQLAlchemy to work with SQLAlchemy.

  • Alembic helps you migrate your data between schema changes.

ourapp/alembic.inialembic/env.pyREADMEscript.py.makoversions/3512b954651e_add_account.py2b1ae634e5cd_add_order_id.py3adcc9a56557_rename_username_field.pymyapp/__init__.pyviews.pymodels.pytemplates/run.pyconfig.pyrequirements.txt
  • You can use NoSQL databases with Flask, but the methods and tools vary between engines.

  • Back up your data!

仍然适用的原则 ✅

  1. Use SQLAlchemy to work with relational databases

    • SQLAlchemy 仍然是 Python 生态中最主流、最强大的 ORM,Flask 项目中的首选方案

    • 核心功能(ORM/SQL Expression)设计经受了时间考验

  2. Use Flask-SQLAlchemy to work with SQLAlchemy

    • Flask-SQLAlchemy 仍然是官方推荐的集成方案(最新版本 3.1.x)

    • 提供了 db.session 管理和 Flask 集成等便利功能

  3. Alembic helps you migrate your data between schema changes

    • Alembic 仍然是 SQLAlchemy 生态的标准迁移工具

    • 现代改进:支持异步(Alembic 1.11+)、更好的 DDL 事务控制

  4. Back up your data!

    • 永恒真理,现在更多通过云数据库的自动备份功能实现(如 AWS RDS 快照)


需要更新的原则 ⚠️

  1. You can use NoSQL databases with Flask, but the methods and tools vary between engines

    • 仍然正确,但现代变化:

      • MongoDB:推荐官方驱动 PyMongo(Flask-PyMongo 已不维护)

      • Redis:直接使用 redis-py,部分场景可用 Flask-Caching

      • 新兴数据库:如 ClickHouse 有专用 Python 驱动

    • 趋势:NoSQL 不再强调 "Flask 扩展",而是直接使用各数据库的官方 SDK


现代补充建议 ✨

  1. 异步支持

    • SQLAlchemy 2.0+ 全面支持 async(需配合 asyncpg/aiomysql

    • Flask 本身不支持异步,但可通过 Quart(Flask 异步克隆)实现

  2. 替代方案

    • 简单项目可考虑 PeeWee 或 SQLModel(SQLAlchemy + Pydantic)

    • Django 开发者可能更喜欢 Flask-Marshmallow 序列化

  3. 云原生趋势

    • 无服务器场景考虑 Serverless 数据库(如 PlanetScale、Neon)

    • 分布式 SQL(如 CockroachDB)有完善 SQLAlchemy 支持

  4. 开发体验

    • 使用 Flask-Migrate 简化 Alembic 操作(flask db migrate

    • 推荐 SQLAlchemy 2.0 声明式表配置(更简洁的语法)

  5. 安全建议

    • 一定要启用 SQLAlchemy 的 echo=False 生产环境

    • 使用 scoped_session 避免多线程问题


过时/不推荐的做法 🚫

  • 避免旧版 SQLAlchemy 1.3 的写法(如 query.get() 已弃用)

  • 不再推荐使用 Flask-MongoEngine 等封装过度的 NoSQL 扩展

  • 避免手动拼接 SQL(SQLAlchemy Core 已能处理绝大多数场景)

现代 Flask 项目数据库选择建议:PostgreSQL + SQLAlchemy 2.0 + Alembic 仍是黄金组合。

十、Handling forms

Summary

  • Forms can be scary from a security perspective.

# ourapp/forms.pyfrom flask_wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Emailclass EmailPasswordForm(Form):email = StringField('Email', validators=[DataRequired(), Email()])password = PasswordField('Password', validators=[DataRequired()])
  • WTForms (and Flask-WTF) make it easy to define, secure and render your forms.

  • Use the CSRF protection provided by Flask-WTF to secure your forms.

{# ourapp/templates/login.html #}{% extends "layout.html" %}
<html><head><title>Login Page</title></head><body><form action="{{ url_for('login') }}" method="post"><input type="text" name="email" /><input type="password" name="password" />{{ form.csrf_token }}</form></body>
</html>
  • You can use Flask-WTF to protect AJAX calls against CSRF attacks too.

  • Define custom form validators to keep validation logic out of your views.

  • Use the WTForms field rendering to render your form’s HTML so you don’t have to update it every time you make some changes to the form definition.

仍然适用的原则 ✅

  1. Forms can be scary from a security perspective

    • 表单安全仍是重中之重(CSRF/XSS/SQL 注入等风险依然存在)

  2. Use the CSRF protection provided by Flask-WTF to secure your forms

    • Flask-WTF 的 CSRF 保护仍是标准方案(最新版本 1.2.x)

    • 现代补充:REST API 推荐改用 JWT/OAuth2 + SameSite cookies

  3. Define custom form validators to keep validation logic out of your views

    • 验证逻辑与视图分离仍是最佳实践

    • 现代扩展:可结合 Pydantic 进行更复杂的验证


需要更新的原则 ⚠️

  1. WTForms (and Flask-WTF) make it easy to define, secure and render your forms

    • 仍然可用但不再是唯一选择,现代替代方案:

      • 前端框架(React/Vue)直接处理表单 + Flask 仅作 API 验证

      • 使用 Pydantic 进行数据验证(尤其适合 API 项目)

      • 简单场景可用 flask.request.get_json() 直接处理

  2. You can use Flask-WTF to protect AJAX calls against CSRF attacks too

    • 仍然有效但现代方案更倾向于:

      • 对 API 使用 JWT + CORS 限制

      • 启用 SameSite=Strict cookie 策略

      • 框架内置 CSRF(如 Next.js/Angular 自带防护)

  3. Use the WTForms field rendering to render your form’s HTML

    • 服务器端渲染表单逐渐减少,现代趋势:

      • 前端动态渲染(React/Vue/Svelte 表单组件库)

      • 仅用 WTForms 做验证,前端单独实现 UI

      • HTMX 等新技术实现渐进式增强


现代补充建议 ✨

  1. 混合验证架构

    # 结合 Pydantic 和 WTForms 的优点
    from pydantic import BaseModel
    from flask_wtf import FlaskFormclass APIModel(BaseModel):  # API 请求验证name: strage: intclass WebForm(FlaskForm):  # 传统网页表单name = StringField(validators=[DataRequired()])

  2. 安全增强

    • 始终启用 WTF_CSRF_ENABLED = True(默认已开启)

    • 对敏感操作添加二次验证(如 CAPTCHA)

  3. 现代替代工具

    • 前端表单:Formik(React)、VeeValidate(Vue)

    • 验证库:Pydantic、marshmallow

    • 安全:Flask-Talisman(强制 HTTPS/HSTS)

  4. 性能优化

    • 对静态表单考虑缓存渲染结果

    • 使用 flask-caching 缓存验证规则

过时/不推荐的做法 🚫

  • 避免完全依赖 WTForms 渲染前端(难以适应现代 UI 需求)

  • 不要手动拼接 HTML 表单(易导致 XSS 漏洞)

  • 避免在 AJAX 中直接提交 application/x-www-form-urlencoded(推荐 JSON)


当前推荐方案

场景推荐工具
传统多页应用Flask-WTF + WTForms
SPA 前后端分离Pydantic + 前端表单库
混合应用(HTMX)WTForms 验证 + 部分渲染

关键结论:WTForms 仍然安全可靠,但现代项目更倾向于将表单逻辑交给前端,后端专注数据验证。对于新项目,建议优先考虑 Pydantic + 前端框架的组合。

十一、Patterns for handling users

Summary

  • Use the itsdangerous package to create and validate tokens sent to an email address.

# ourapp/util/security.pyfrom itsdangerous import URLSafeTimedSerializerfrom .. import appts = URLSafeTimedSerializer(app.config["SECRET_KEY"])
# ourapp/views.pyfrom flask import redirect, render_template, url_forfrom . import app, db
from .forms import EmailPasswordForm
from .util import ts, send_email@app.route('/accounts/create', methods=["GET", "POST"])
def create_account():form = EmailPasswordForm()if form.validate_on_submit():user = User(email = form.email.data,password = form.password.data)db.session.add(user)db.session.commit()# Now we'll send the email confirmation linksubject = "Confirm your email"token = ts.dumps(self.email, salt='email-confirm-key')confirm_url = url_for('confirm_email',token=token,_external=True)html = render_template('email/activate.html',confirm_url=confirm_url)# We'll assume that send_email has been defined in myapp/util.pysend_email(user.email, subject, html)return redirect(url_for("index"))return render_template("accounts/create.html", form=form)
{# ourapp/templates/email/activate.html #}Your account was successfully created. Please click the link below<br>
to confirm your email address and activate your account:<p>
<a href="{{ confirm_url }}">{{ confirm_url }}</a>
</p><p>
--<br>
Questions? Comments? Email hello@myapp.com.
</p>
  • You can use these tokens to validate emails when a user creates an account, changes their email or forgets their password.

# ourapp/views.py@app.route('/confirm/<token>')
def confirm_email(token):try:email = ts.loads(token, salt="email-confirm-key", max_age=86400)except:abort(404)user = User.query.filter_by(email=email).first_or_404()user.email_confirmed = Truedb.session.add(user)db.session.commit()return redirect(url_for('signin'))
  • Authenticate users using the Flask-Login extension to avoid dealing with a bunch of session management stuff yourself.

  • Always think about how a malicious user could abuse your app to do things that you didn’t intend.

仍然适用的原则 ✅

  1. Authenticate users using Flask-Login

    • Flask-Login(最新版本 0.6.x)仍是管理用户会话的事实标准

    • 核心功能稳定:@login_requiredcurrent_userremember_me 等

    • 现代补充:支持自定义用户加载器(包括异步场景)

  2. Always think about security

    • "考虑恶意用户行为"是永恒原则,现代威胁模型新增:

      • API 滥用(暴力破解/爬虫)→ 需增加速率限制(Flask-Limiter)

      • 密码 spraying 攻击→ 强制 MFA(如 Flask-Dance 支持 OAuth)

      • 供应链攻击→ 依赖项扫描(pip-audit)


需要更新的原则 ⚠️

  1. Use itsdangerous for email tokens

    • 仍然可用但不再是首选方案,现代替代方案:

      • 专用令牌库:PyJWT(RFC 7519 标准 JWT)

      • 安全增强:使用 cryptography 直接生成加密令牌

      • 云服务:AWS Cognito/Auth0 等托管服务

    • 仅推荐 itsdangerous 用于简单场景(如开发环境)


现代补充建议 ✨

认证架构升级
# 现代认证组合示例(2024)
from flask_jwt_extended import JWTManager  # REST API
from flask_principal import Principal  # 权限管理
from authlib.integrations.flask_client import OAuth  # 第三方登录jwt = JWTManager(app)  # 替代部分 itsdangerous 场景
oauth = OAuth(app)
关键实践
  1. 密码重置/邮件验证

    • 改用 时间受限的 JWTflask-jwt-extended

    • 必须使用 一次性令牌(即使 itsdangerous 也需自行实现)

  2. 会话管理

    • 启用 SESSION_PROTECTION = "strong"(Flask-Login)

    • 生产环境必须使用 Secure/HttpOnly cookies

  3. 现代威胁防护

    # 安全头设置(Flask-Talisman)
    talisman = Talisman(app,content_security_policy=...,force_https=True
    )

  4. 审计工具

    • 使用 bandit 扫描安全漏洞

    • 依赖项检查:safety check 或 GitHub Dependabot

过时/不推荐的做法 🚫

  • 避免直接使用 itsdangerous 处理敏感操作(如密码重置)

  • 不要自行实现加密算法(应使用 passlib 或 bcrypt

  • 避免将 Flask-Login 用于纯 API 项目(应改用 JWT)


2024 年推荐方案

场景工具选择
传统网页应用Flask-Login + Flask-WTF CSRF
REST APIflask-jwt-extended + OAuth2
邮件验证/密码重置PyJWT(而非 itsdangerous)
第三方登录Authlib/OAuthLib

核心建议

  1. 新项目优先考虑 JWT + OAuth 2.0 生态

  2. 维护旧项目时可继续使用 itsdangerous,但需增加速率限制

  3. 必须实施 密码哈希(argon2id/bcrypt) + HTTPS 强制跳转

十二、Deployment

Summary

  • Three good choices for hosting Flask apps are AWS EC2, Heroku and Digital Ocean.

  • The basic deployment stack for a Flask application consists of the app, an application runner like Gunicorn and a reverse proxy like Nginx.

(ourapp)$ gunicorn rocket:app
2014-03-19 16:28:54 [62924] [INFO] Starting gunicorn 18.0
2014-03-19 16:28:54 [62924] [INFO] Listening at: http://127.0.0.1:8000 (62924)
2014-03-19 16:28:54 [62924] [INFO] Using worker: sync
2014-03-19 16:28:54 [62927] [INFO] Booting worker with pid: 62927
(ourapp)$ gunicorn rocket:app -p rocket.pid -D
(ourapp)$ cat rocket.pid
63101
(ourapp)$ kill -HUP `cat rocket.pid`
(ourapp)$ kill `cat rocket.pid`
  • Gunicorn should sit behind Nginx and listen on 127.0.0.1 (internal requests) not 0.0.0.0 (external requests).

  • Use Werkzeug’s ProxyFix to handle the appropriate proxy headers in your Flask application.

仍然适用的原则 ✅

  1. 基础部署架构(App → Gunicorn → Nginx)

    • 传统虚拟机部署仍保持此结构,但现代方案更倾向于容器化

    • 新增要求:Nginx 现在需强制配置 HTTP/2 和 TLS 1.3

  2. Gunicorn 监听本地端口

    • 安全规范仍然要求:生产环境必须绑定 127.0.0.1 而非 0.0.0.0

    • 现代补充:Kubernetes 环境下改为通过 Service 暴露

  3. Werkzeug 的 ProxyFix

    • 仍然需要处理反向代理头,但现代方案:

      from werkzeug.middleware.proxy_fix import ProxyFix
      app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)
    • 新增要求:必须显式配置 x_for/x_proto 数量(防伪造)

需要更新的原则 ⚠️

  1. 三大托管服务推荐(EC2/Heroku/Digital Ocean)

    • Heroku:已不再提供免费层(2022年11月取消),性价比下降

    • Digital Ocean:现更推荐其 App Platform(托管容器服务)

    • AWS EC2:仍是主流但非最优选择,现代替代方案:

      • 容器服务:AWS ECS/EKS、Google Cloud Run

      • Serverless:AWS Lambda(Zappa框架)、Vercel

      • 边缘部署:Fly.io、Cloudflare Workers


现代补充建议 ✨

部署架构演进

关键实践升级
  1. 运行时选择

    • 同步应用:仍可用 Gunicorn + gevent

    • 异步应用:改用 Uvicorn(ASGI 服务器,支持 HTTP/2)

  2. 安全强化

    # Nginx 现代配置片段
    location / {proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_set_header X-Forwarded-Proto $scheme;# 必须设置严格 CSPadd_header Content-Security-Policy "default-src 'self'";
    }

  3. 基础设施即代码

    • 使用 Terraform/Pulumi 管理云资源

    • 部署工具:GitHub Actions > Fabric/Capistrano

  4. 性能优化

    • 静态文件移交 CDN(Cloudflare/R2)

    • 启用 Brotli 压缩替代 gzip

过时/不推荐的做法 🚫

  • 避免直接部署裸机/虚拟机(除非有特殊需求)

  • 不要使用 flask run 生产环境(仍常见于教程但极不安全)

  • 避免手动配置服务器(应使用 Docker + CI/CD 自动化)


2024 年推荐方案

场景推荐方案优势
快速原型Fly.io/Render5分钟部署,免费额度
传统应用Docker + EC2平衡控制力与成本
高流量服务Kubernetes + GCP自动伸缩
ServerlessAWS Lambda + API Gateway按需计费

重要趋势

  1. 容器化已成默认选择(即使小型项目)

  2. Serverless 方案成熟(Cold Start 问题显著改善)

  3. 边缘计算兴起(如 Cloudflare Workers 支持 Python)

建议新项目优先考虑:Docker → 托管容器服务(如 Fly.io) 的路径,既保持开发一致性,又降低运维复杂度。

相关文章:

【Flask】Explore-Flask:早期 Flask 生态的实用指南

开源项目&#xff1a;explore-flask/README.rst at master rpicard/explore-flask (github.com) 一、Coding conventions Summary Try to follow the coding style conventions laid out in PEP 8. Try to document your app with docstrings as defined in PEP 257. def…...

STM32 中断系统深度剖析

在嵌入式系统开发领域&#xff0c;STM32 系列微控制器凭借其强大的性能和丰富的资源被广泛应用。中断系统作为 STM32 的关键特性之一&#xff0c;能够极大地提升系统的实时响应能力和多任务处理效率。本文将基于 STM32F4 系列芯片&#xff0c;深入剖析中断与外设中断的原理、配…...

FAST‘25论文解读:HaSiS单索引存储架构实现HTAP数据处理新范式

想象一下这样的场景&#xff1a;每一笔线上交易都能实时更新库存分析&#xff0c;金融应用能在交易发生那一刻完成欺诈检测——既不延迟也不损失性能。这正是HTAP&#xff08;Hybrid Transactional and Analytical Processing&#xff0c;混合事务与分析处理&#xff09;带来的…...

FastAPI:现代高性能Python Web框架的技术解析与实践指南

一、FastAPI的诞生背景与技术定位 在数字化转型的浪潮中,API(应用程序接口)作为连接服务与数据的核心枢纽,其性能与开发效率直接影响业务迭代速度。传统Python框架如Django和Flask虽功能丰富,但在高并发场景下面临性能瓶颈,且缺乏对异步编程的原生支持。FastAPI应运而生…...

缓存 --- 缓存击穿, 缓存雪崩, 缓存穿透

缓存 --- 缓存击穿, 缓存雪崩, 缓存穿透 缓存击穿&#xff08;Cache Breakdown&#xff09;概念原理实际场景代码实现&#xff08;互斥锁方案&#xff09; 缓存雪崩&#xff08;Cache Avalanche&#xff09;概念原理实际场景代码实现&#xff08;随机过期时间&#xff09; 缓存…...

Android 中实现图片翻转动画(卡片翻转效果)

1、简述 通过 ObjectAnimator 和 AnimatorSet 可以实现图片的翻转动画,并在翻转过程中切换图片,同时避免图片被镜像。 ObjectAnimator 是 Android 动画框架中的一个类,用于对对象的属性进行动画效果处理。它通过改变对象的属性值来实现动画效果,非常适合实现复杂的动画,如…...

【论文阅读21】-PSOSVM-CNN-GRU-Attention-滑坡预测(2024-12)

这篇论文主要提出并验证了一种新型的混合智能模型&#xff08;PSOSVM-CNN-GRU-Attention&#xff09;&#xff0c;用于准确预测滑坡的点位移&#xff0c;并构建可靠的位移预测区间。通过对Baishuihe滑坡和Shuping滑坡的案例分析&#xff0c;展示了该模型的出色性能。 [1] Zai D…...

蓝牙 6.0 发布,解锁无线科技新可能

在5G和Wi-Fi 7高速发展的时代&#xff0c;蓝牙技术始终以独特优势深度融入日常生活。从无线耳机到智能家居&#xff0c;它凭借低功耗、高兼容的特性&#xff0c;悄然连接各类智能设备&#xff0c;打造无缝的数字生活体验。无论是聆听音乐、智能门禁还是健康监测&#xff0c;蓝牙…...

EasyCVR视频智能分析平台助力智慧园区:全场景视频监控摄像头融合解决方案

一、方案背景 在智慧园区建设的浪潮下&#xff0c;设备融合、数据整合与智能联动已成为核心诉求。视频监控作为智慧园区的“视觉中枢”&#xff0c;其高效整合直接影响园区的管理效能与安全水平。然而&#xff0c;园区内繁杂的视频监控设备生态——不同品牌、型号、制式的摄像…...

PHP发送邮件

一、安装PHPMailer 进入项目目录下&#xff0c;执行&#xff1a;composer require phpmailer/phpmailer 二、使用 <?php use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception;require vendor/autoload.php;$mail new PHPMailer(true); header("…...

为您的照片提供本地 AI 视觉:使用 Llama Vision 和 ChromaDB 构建 AI 图像标记器

有没有花 20 分钟浏览您的文件夹以找到心中的特定图像或屏幕截图&#xff1f;您并不孤单。 作为工作中的产品经理&#xff0c;我总是淹没在竞争对手产品的屏幕截图、UI 灵感以及白板会议或草图的照片的海洋中。在我的个人生活中&#xff0c;我总是捕捉我在生活中遇到的事物&am…...

Spark on K8s 在 vivo 大数据平台的混部实战与优化

一、Spark on K8s 简介 (一)定义与架构 Spark on K8s 是一种将 Spark 运行在 Kubernetes(K8s)集群上的架构,由 K8s 直接创建 Driver 和 Executor 的 Pod 来运行 Spark 作业。其架构如下。 Driver Pod:相当于 Spark 集群中的 Driver,负责作业的调度和管理,它会根据作业…...

K8S节点出现Evicted状态“被驱逐”

在Kubernetes集群中&#xff0c;Pod状态为“被驱逐&#xff08;evicted&#xff09;”表示Pod无法在当前节点上继续运行&#xff0c;已被集群从节点上移除。 问题分析&#xff1a; 节点磁盘空间不足 &#xff0c;使用df -h查看磁盘使用情况 可以看到根目录 / 已100%满&#x…...

重学React(一):描述UI

背景&#xff1a;React现在已经更新到19了&#xff0c;文档地址也做了全面的更新&#xff0c;上一次系统性的学习还是在16-17的大版本更新。所以&#xff0c;现在就开始重新学习吧&#xff5e; 学习内容&#xff1a; React官网教程&#xff1a;https://zh-hans.react.dev/lea…...

CSS核心笔记002

margin塌陷问题 第一个子元素的上margin会作用在父元素上, 最后一个子元素的下margin会作用在父元素上解决 1. 给父元素设置 不为0的pandding 2. 给父元素设置宽度不为0 的border 3. 给父元素设置样式 overflow:hiddenmargin合并问题 兄弟元素的下外margin和会下面兄弟的上…...

遨游通讯发布国产化旗舰三防手机AORO AU1:以自主可控重塑工业安全

在全球产业链加速重构的背景下&#xff0c;国产化技术突破已成为工业领域高质量发展的核心驱动力。作为专精特新中小企业&#xff0c;遨游通讯始终以“让世界更安全、更高效、更简单”为使命&#xff0c;深耕“危、急、特”场景智能通信设备的研发。近日&#xff0c;遨游通讯正…...

【Python】Selenium切换网页的标签页的写法(全!!!)

在使用selenium做网站爬取测试的时候&#xff0c;我们经常会遇到一些需要点击的元素&#xff0c;才能点击到我们想要进入的页面&#xff0c; 于是我们就要模拟 不断地 点点点击 鼠标的样子。 这个时候网页上就会有很多的标签页&#xff0c;你的浏览器网页标签栏 be like: 那…...

洛谷P1177【模板】排序:十种排序算法全解(1)

扯谈 之前我已经把十大排序算法全讲了一遍&#xff08;具体详见专栏C排序算法&#xff09;,今天我们来用一道简单的题目总结实战一下。 算法实现 一、桶排序&#xff08;Bucket Sort&#xff09; ‌适用场景‌&#xff1a;数据范围已知且较小&#xff08;需根据测试数据调整…...

pytorch 51 GroundingDINO模型导出tensorrt并使用c++进行部署,53ms一张图

本专栏博客第49篇文章分享了将 GroundingDINO模型导出onnx并使用c++进行部署,并尝试将onnx模型转换为trt模型,fp16进行推理,可以发现推理速度提升了一倍。为此对GroundingDINO的trt推理进行调研,发现 在GroundingDINO-TensorRT-and-ONNX-Inference项目中分享了模型导出onnx…...

中间件--ClickHouse-11--部署示例(Linux宿主机部署,Docker容器部署)

一、Linux宿主机部署 1、环境准备 操作系统&#xff1a;推荐使用 CentOS 7/8 或 Ubuntu 18.04/20.04。硬件要求&#xff1a; 至少 2 核 CPU 和 4GB 内存。足够的磁盘空间&#xff08;根据数据量评估&#xff09;。CPU需支持SSE4.2指令集&#xff08;可通过以下命令检查&#…...

DeepSeek和Excel结合生成动态图表

文章目录 一、前言二、3D柱状图案例2.1、pyecharts可视化官网2.2、Bar3d-Bar3d_puch_card2.3、Deepseek2.4、WPS2.5、动态调整数据 一、前言 最近在找一些比较炫酷的动态图表&#xff0c;用于日常汇报&#xff0c;于是找到了 DeepseekExcel王牌组合&#xff0c;其等同于动态图…...

[Python入门学习记录(小甲鱼)]第6章 函数

函数就是把代码整理打包的东西 6.1 Python的函数基操 函数的基本操作 6.1.1 创建和调用函数 def myfunc():print(1)print(2)print(3) myfunc() # 输出 1 2 3 带换行 调用时会自动找函数定义6.1.2 函数的参数 def add(num1, num2):print(num1 num2) add(1, 2) # 输出 3…...

Ubuntu20.04 部署llama-factory问题集

llama3 微调教程之 llama factory 的 安装部署与模型微调过程&#xff0c;模型量化和gguf转换。_llamafactory 部署-CSDN博客 1.跟着教程 llama-factory下载不下来 来&#xff0c;试着换源&#xff0c;多试几次&#xff0c;就可以成功了。。。 2.跟着教程&#xff0c;发现无法…...

海量聊天数据处理:基于Spring Boot与SharingJDBC的分库分表策略及ClickHouse冷热数据分离

引言 随着互联网应用的快速发展&#xff0c;每天产生的聊天记录数量级已经达到了惊人的程度。以2000万条/天为例&#xff0c;一年下来就是大约7.3亿条记录。如此庞大的数据量给数据库的设计和管理带来了前所未有的挑战。本文将探讨如何使用SharingJDBC整合Spring Boot技术来实…...

EAL4+与等保2.0:解读中国网络安全双标准

EAL4与等保2.0&#xff1a;解读中国网络安全双标准 在当今数字化时代&#xff0c;网络安全已成为各个行业不可忽视的重要议题。特别是在金融、政府、医疗等领域&#xff0c;保护信息的安全性和隐私性显得尤为关键。在中国&#xff0c;EAL4和等级保护2.0&#xff08;简称“等保…...

GreatSQL启动崩溃:jemalloc依赖缺失问题排查

GreatSQL启动崩溃&#xff1a;jemalloc依赖缺失问题排查 故障现象&#xff1a; 之前协助用户安装 GreatSQL 测试环境时&#xff0c;遇到一个 case&#xff0c;数据库初始化时没有报错&#xff0c;但是使用mysqld_safe去启动&#xff0c;会直接 crash ,详情报错如下&#xff1…...

大语言模型助力 Support Case 分析,提升云服务效率

1. 背景 技术工单&#xff08;Support Case&#xff09;是企业在进行云平台操作的时候通常会用到的一种技术支持类型&#xff0c;提供的技术支持通常包括所有的云服务的使用问题、账单问题、限制额度提升等等。对于云平台的管理者而言&#xff0c;对各个 BU 所提的工单进行统计…...

ubuntu磁盘挂载

1、‌查看磁盘设备及分区‌ 命令‌&#xff1a;列出所有块设备&#xff08;磁盘及分区&#xff09; lsblk 0表示此块未挂载 2、格式化分区 sudo mkfs.ext4 /dev/sdb 注意sdb换成自己的块名称 3、创建挂载点目录‌ sudo mkdir -p /mnt/data4、永久挂载 sudo blkid /dev…...

在pycharm中搭建yolo11分类检测系统--PyQt5学习(二)

第二部分 测试本地pycharm通过程序连接远程服务器autodl 模型的推理需要借助远程服务器autodl&#xff0c;但是界面的运行是在pycharm中&#xff0c;我的设想是按钮调用一个py文件就好了。 1. 本地运行PyQt5界面。 2. 当需要载入权重时&#xff0c;通过SSH连接到AutodL服务…...

chili3d调试笔记8 打印零件属性 浏览器元素展开

无效&#xff0c; 返回的是节点不是坐标啥的&#xff0c; 找他的属性 把document和selectednote&#xff08;空集&#xff09;传给handleshowproperty方法 怎么获得selectnotes和selectnotes的property值 有selectnotes运行这段就行了 明天再搞 ----------------------------…...