当你的 Flask 应用从“Hello World”成长为一个包含数据库、用户认证、多个页面的真实项目时,把所有代码塞进一个 app.py 文件会导致代码极其臃肿且难以维护。
为了解决这个问题,Flask 社区沉淀出了一套标准的中大型项目结构。这套结构的核心思想是:模块化(蓝图) 和 应用工厂模式。
📂 标准 Flask 项目目录结构
这是一个经过生产环境验证的、结构清晰的 Flask 项目目录树:
my_flask_project/
│
├── app/ # 📁 核心应用代码目录(所有业务逻辑都在这里)
│ ├── __init__.py # 🌟 应用工厂 (create_app),项目的灵魂
│ ├── extensions.py # 🔌 扩展实例化 (db, migrate, login_manager 等)
│ ├── models.py # 🗄️ 数据库模型 (SQLAlchemy Models)
│ │
│ ├── main/ # 📦 蓝图:主页面/通用路由 (如首页、关于)
│ │ ├── __init__.py # 注册蓝图
│ │ └── routes.py # 具体的视图函数
│ │
│ ├── auth/ # 📦 蓝图:用户认证 (登录、注册、登出)
│ │ ├── __init__.py
│ │ └── routes.py
│ │
│ ├── api/ # 📦 蓝图:RESTful API (前后端分离接口)
│ │ ├── __init__.py
│ │ └── routes.py
│ │
│ ├── templates/ # 🎨 HTML 模板文件 (Jinja2)
│ │ ├── base.html # 基础布局模板
│ │ ├── main/
│ │ └── auth/
│ │
│ └── static/ # 🖼️ 静态文件 (CSS, JS, 图片, 字体)
│ ├── css/
│ ├── js/
│ └── images/
│
├── migrations/ # 🔄 数据库迁移文件 (由 Flask-Migrate 生成)
├── tests/ # 🧪 单元测试和集成测试代码
│
├── config.py # ⚙️ 配置文件 (区分开发、测试、生产环境)
├── requirements.txt # 📦 项目依赖包列表 (pip freeze)
├── .env # 🔒 环境变量 (存放密钥、数据库密码,**绝不提交到 Git**)
├── .gitignore # 🚫 Git 忽略文件配置
└── run.py # 🚀 项目启动入口文件🧠 核心机制解析
要理解这个结构,必须掌握以下三个核心概念:
1. 应用工厂模式 (app/__init__.py)
不再使用全局的 app = Flask(__name__),而是写一个函数来“制造”应用实例。
好处:方便创建多个应用实例(例如在测试时),避免循环导入问题。
# app/__init__.py
from flask import Flask
from config import config_dict
from app.extensions import db, migrate
def create_app(config_name='default'):
app = Flask(__name__)
# 加载配置
app.config.from_object(config_dict[config_name])
# 初始化扩展 (绑定到 app)
db.init_app(app)
migrate.init_app(app, db)
# 注册蓝图
from app.main import main_bp
app.register_blueprint(main_bp)
from app.auth import auth_bp
app.register_blueprint(auth_bp, url_prefix='/auth')
return app2. 扩展分离 (app/extensions.py)
为了解决 Python 的循环导入问题(例如 models.py 需要 db,而 __init__.py 需要 models),我们将扩展的实例化单独抽离出来。
# app/extensions.py
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
# 先实例化,但不绑定 app
db = SQLAlchemy()
migrate = Migrate()
login_manager = LoginManager()3. 蓝图拆分 (app/main/, app/auth/)
蓝图(Blueprint)相当于子应用。我们按功能模块而不是按文件类型来拆分代码。
每个蓝图文件夹里都有一个 __init__.py 用于创建蓝图对象,和一个 routes.py 用于写路由。
# app/auth/__init__.py
from flask import Blueprint
# 创建蓝图,'auth' 是蓝图名称,__name__ 帮助定位模板
auth_bp = Blueprint('auth', __name__, template_folder='../templates/auth')
# 导入路由(必须在蓝图创建后导入,避免循环引用)
from app.auth import routes # app/auth/routes.py
from app.auth import auth_bp
@auth_bp.route('/login')
def login():
return 'Login Page'⚙️ 配置管理 (config.py)
在实际开发中,开发环境(本地 SQLite)和生产环境(线上 MySQL/PostgreSQL)的配置是不同的。使用面向对象的方式管理配置非常优雅:
# config.py
import os
from dotenv import load_dotenv
# 加载 .env 文件中的环境变量
basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard-to-guess-string'
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'dev-data.sqlite')
class ProductionConfig(Config):
DEBUG = False
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
# 字典映射,方便在工厂模式中通过字符串选择配置
config_dict = {
'development': DevelopmentConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}🚀 启动项目 (run.py)
最后,我们需要一个入口文件来启动这个工厂制造出来的应用:
# run.py
import os
from app import create_app
# 从环境变量读取配置,默认使用开发环境
config_name = os.getenv('FLASK_CONFIG', 'development')
app = create_app(config_name)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)运行方式:
python run.py(注:在 Flask 2.2+ 中,也可以不使用 run.py,而是通过命令行 flask --app run run --debug 来启动,但保留 run.py 对很多开发者来说更直观。)
💡 最佳实践建议
.env文件极其重要:永远不要把数据库密码、SECRET_KEY硬编码在代码里。使用python-dotenv库读取.env文件,并确保.env被加入了.gitignore。- 模板和静态文件的位置:
- 默认情况下,Flask 会在
app/目录下寻找templates/和static/。 - 如果蓝图需要独立的模板,可以在创建蓝图时指定:
Blueprint('auth', __name__, template_folder='templates')。
- 保持
__init__.py干净:应用工厂文件只负责“组装”(加载配置、初始化扩展、注册蓝图),绝对不要在里面写具体的业务路由。
掌握了这个结构,你的 Flask 项目就具备了支撑中大型商业应用的能力。接下来,你可以开始往里面填充 数据库模型 (models.py) 和 具体的蓝图路由 了!