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

news2025/4/24 2:42:38

开源项目: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__.py
    views.py
    models.py
    forms.py
    static/
    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 Flask

app = 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__.py
  models.py
  views.py
  templates/
  static/
# app.py or app/__init__.py

app = 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.py

from 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.py

from flask_cache import Cache
from flask import Flask

app = 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 need
    return 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.py

from functools import wraps
from datetime import datetime

from flask import flash, redirect, url_for

from flask_login import current_user

def 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__.py
    templates/
        layout.html
        home/
            layout.html
            index.html
            about.html
            signup.html
            login.html
        dashboard/
            layout.html
            news_feed.html
            welcome.html
            find_friends.html
        profile/
            layout.html
            timeline.html
            about.html
            photos.html
            friends.html
            edit.html
        settings/
            layout.html
            privacy.html
            security.html
            general.html
    views/
        __init__.py
        home.py
        dashboard.py
        profile.py
        settings.py
    static/
        style.css
        logo.png
    models.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__.py

from flask import Flask
from .views.profile import profile

app = 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.py

from flask import Blueprint, render_template

profile = Blueprint('profile', __name__, url_prefix='/<user_url_slug>')

# [...]
# facebook/__init__.py

from flask import Flask
from .views.profile import profile

app = 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.html
    index.html
    about.html
    profile/
        layout.html
        index.html
    photos.html
    admin/
        layout.html
        index.html
        analytics.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__.py
    static/
    templates/
    views/
    models.py
run.py
  • Separate third-party libraries from your own static files.

static/
    css/
        lib/
            bootstrap.css
        style.css
        home.css
        admin.css
    js/
        lib/
            jquery.js
        home.js
        admin.js
    img/
        logo.svg
        favicon.ico
  • Specify the location of your favicon in your templates.

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

# myapp/util/assets.py

from flask_assets import Bundle, Environment
from .. import app

bundles = {

    '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__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__, instance_relative_config=True)

app.config.from_object('config')
app.config.from_pyfile('config.py')

db = SQLAlchemy(app)
# ourapp/models.py

from . import db

class Engine(db.Model):

    # Columns

    id = 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.ini
    alembic/
        env.py
        README
        script.py.mako
        versions/
            3512b954651e_add_account.py
            2b1ae634e5cd_add_order_id.py
            3adcc9a56557_rename_username_field.py
    myapp/
        __init__.py
        views.py
        models.py
        templates/
    run.py
    config.py
    requirements.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.py

from flask_wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Email

class 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 FlaskForm
    
    class APIModel(BaseModel):  # API 请求验证
        name: str
        age: int
    
    class 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.py

from itsdangerous import URLSafeTimedSerializer

from .. import app

ts = URLSafeTimedSerializer(app.config["SECRET_KEY"])
# ourapp/views.py

from flask import redirect, render_template, url_for

from . 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 link
        subject = "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.py
        send_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 = True

    db.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;
        # 必须设置严格 CSP
        add_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) 的路径,既保持开发一致性,又降低运维复杂度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2341166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文阅读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;园区内繁杂的视频监控设备生态——不同品牌、型号、制式的摄像…

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

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

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…

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

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

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

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

DeepSeek和Excel结合生成动态图表

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

Ubuntu20.04 部署llama-factory问题集

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

大语言模型助力 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…

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

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

新书速览|DeepSeek移动端AI应用开发:基于Android与iOS

《DeepSeek移动端AI应用开发&#xff1a;基于Android与iOS》 1 本书内容 《DeepSeek移动端AI应用开发:基于Android与iOS》深入剖析了DeepSeek平台的架构原理、API调用及开发实践等核心内容&#xff0c;助力读者在Android与iOS移动端高效集成DeepSeek API&#xff0c;打造出契…

Android调用springboot接口上传大字段,偶现接口超时的优化

介绍 最近有个功能&#xff0c;Android通过okhttp上传实体类&#xff0c;实体类包含一个大字段&#xff0c;上传的字符串长度达到300k&#xff0c;偶现接口超时的情况&#xff0c;大概100次有5次&#xff0c;看日志发现数据并没有到达接口&#xff0c;可能在网络传输中就超时了…

react组件之间如何使用接收到的className(封装一个按钮案例)

带有hover渐变效果 一、父组件 import LineGradientBox from ../line-gradient-box; import styles from ./index.module.scss;<LineGradientBoxfontSize{20}className{styles.btn_height}textSign upwidth"100%"onClick{() > {navigate(/sign-up);}} /> …

JavaScript 数组常用方法解析

1. concat - 合并数组 语法&#xff1a; const newArray oldArray.concat(value1, value2, ..., arrayN); 作用&#xff1a; 将当前数组与其他数组或值合并&#xff0c;返回一个新数组&#xff0c;原数组不变。 测试案例&#xff1a; const arr1 [1, 2, 3]; const arr2…

09.传输层协议 ——— TCP协议

文章目录 TCP协议 谈谈可靠性TCP协议格式 序号与确认序号窗口大小六个标志位 确认应答机制&#xff08;ACK&#xff09;超时重传机制连接管理机制 三次握手四次挥手 流量控制滑动窗口拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结基于TCP的应用层协议 TCP协…

数字化转型“变形记”:中钧科技经营帮如何让企业长出“智慧骨骼”

数字化转型就像给企业安装一个"智慧引擎"&#xff0c;而中钧科技的经营帮平台就是这台引擎的智能控制系统。让我们用"人体"来打个比方——当企业的数据、流程、决策像神经脉络般打通&#xff0c;才能真正实现灵活运转。下面就以经营帮的五大核心板块为例&a…

【问题解决】centos7已经不维护了,如何继续使用yum源?

背景 CentOS 7 已于2024年6月30日停止维护&#xff0c;在停止维护后我们之前配置的国内镜像源大多都是空目录了&#xff0c;即在线国内镜像源不可用,就像下边这样提示&#xff1a; [rootbogon yum.repos.d]# yum install vim 已加载插件&#xff1a;fastestmirror Loading mi…