Flask 项目结构:从零开始搭建一个清晰的开发框架
当你第一次接触 Flask 框架时,可能只是写一个 app.py 文件,几行代码就能跑起一个本地服务器。这确实很轻量,适合快速验证想法。但随着功能越来越多,项目变得越来越臃肿,代码混乱、难以维护,这时候你就会意识到:一个合理的 Flask 项目结构,就像盖房子前的图纸,决定了整个系统的可扩展性和可维护性。
今天,我们就来手把手搭建一个适合中小型项目的 Flask 项目结构。不讲虚的,只讲实用,让你的代码不再“一团乱麻”。
为什么需要规范的 Flask 项目结构?
想象一下,你正在开发一个博客系统,功能包括用户登录、文章发布、评论管理、分类筛选。如果所有代码都写在 app.py 里,随着功能增加,这个文件会迅速膨胀到上千行。你每次改个功能,都得在几页代码中翻找,调试起来非常痛苦。
这就是“没有结构”的代价。而一个良好的 Flask 项目结构,能带来以下好处:
- 代码职责分离,便于团队协作
- 功能模块化,可复用性强
- 易于测试和部署
- 项目长期维护更轻松
所以,规范的 Flask 项目结构,是你从“写脚本”迈向“做项目”的关键一步。
推荐的 Flask 项目结构布局
下面是一个经过实践验证的典型 Flask 项目结构,适合大多数中小型 Web 应用:
my_flask_app/
│
├── app/
│ ├── __init__.py # 初始化 Flask 应用,注册蓝图
│ ├── models.py # 数据库模型定义(如 User、Post)
│ ├── views/ # 视图函数(路由和处理逻辑)
│ │ ├── __init__.py
│ │ ├── auth.py # 登录注册相关路由
│ │ ├── blog.py # 博客文章相关路由
│ │ └── api.py # API 接口(可选)
│ ├── static/ # 静态文件(CSS、JS、图片)
│ ├── templates/ # HTML 模板文件
│ │ ├── base.html # 基础模板
│ │ ├── index.html # 首页
│ │ ├── auth/
│ │ └── blog/
│ └── utils/ # 工具函数(如加密、邮件发送)
│ ├── decorators.py # 自定义装饰器
│ └── helpers.py # 常用辅助函数
│
├── config.py # 配置文件(开发、生产环境)
├── requirements.txt # 依赖包列表
├── run.py # 启动脚本(替代直接运行 app.py)
└── .env # 环境变量(数据库密码、密钥等)
这个结构清晰地划分了职责:模型、视图、模板、静态资源、配置、工具函数等各司其职。
项目初始化:从创建文件夹开始
我们来一步步搭建这个结构。假设你已经安装了 Python 和 pip。
mkdir my_flask_app
cd my_flask_app
python -m venv venv
source venv/bin/activate # Linux/Mac
pip install flask flask-sqlalchemy python-dotenv
接下来,创建项目文件和目录:
mkdir app
mkdir app/static app/templates app/views app/utils
touch config.py requirements.txt run.py .env
touch app/__init__.py app/models.py app/views/__init__.py
touch app/templates/base.html app/templates/index.html
touch app/utils/decorators.py app/utils/helpers.py
现在,你的项目结构就搭好了,接下来我们逐步填充内容。
核心配置文件:config.py 的作用
config.py 是整个应用的“心脏”,它定义了不同环境下的配置参数。比如开发环境和生产环境的数据库地址、密钥等。
import os
class Config:
# 应用密钥,用于会话加密
SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key-123456'
# 数据库配置(使用 SQLite,适合开发)
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///app.db'
# 是否自动提交数据库变更
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 可选:邮件配置
MAIL_SERVER = 'smtp.gmail.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
class DevelopmentConfig(Config):
DEBUG = True
class ProductionConfig(Config):
DEBUG = False
config = {
'development': DevelopmentConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}
💡 注释:
SECRET_KEY是 Flask 会话安全的关键,不能明文写死。建议使用os.urandom(24)生成随机值。SQLALCHEMY_TRACK_MODIFICATIONS关闭后可提升性能。
应用初始化:app/init.py 的职责
这个文件是 Flask 应用的入口,负责创建应用实例并注册蓝图。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import config
import os
db = SQLAlchemy()
def create_app(config_name=None):
# 创建 Flask 应用实例
app = Flask(__name__)
# 加载配置(默认为 development)
if config_name is None:
config_name = os.getenv('FLASK_ENV', 'default')
# 应用配置
app.config.from_object(config[config_name])
# 初始化数据库
db.init_app(app)
# 注册蓝图
from app.views.auth import auth_bp
from app.views.blog import blog_bp
from app.views.api import api_bp
app.register_blueprint(auth_bp, url_prefix='/auth')
app.register_blueprint(blog_bp, url_prefix='/blog')
app.register_blueprint(api_bp, url_prefix='/api')
# 注册模板上下文处理器(让所有模板都能访问当前用户)
@app.context_processor
def inject_user():
# 这里可以添加当前用户信息逻辑
return {'user': None}
return app
💡 注释:
register_blueprint是 Flask 模块化的核心机制。将不同功能拆分为独立蓝图,避免主应用文件臃肿。url_prefix为每个蓝图设置统一前缀,便于管理。
模块化视图:使用蓝图组织路由
以“用户登录”功能为例,我们创建一个独立的蓝图 auth.py。
from flask import Blueprint, render_template, request, redirect, url_for, flash
from werkzeug.security import generate_password_hash, check_password_hash
from app.models import User
from app import db
auth_bp = Blueprint('auth', __name__, url_prefix='/auth')
@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# 查询用户
user = User.query.filter_by(username=username).first()
# 验证密码
if user and check_password_hash(user.password, password):
flash('登录成功!', 'success')
return redirect(url_for('blog.index'))
else:
flash('用户名或密码错误', 'error')
return render_template('auth/login.html')
@auth_bp.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# 检查用户名是否已存在
if User.query.filter_by(username=username).first():
flash('用户名已存在', 'error')
return redirect(url_for('auth.register'))
# 创建新用户(密码加密存储)
hashed_password = generate_password_hash(password)
new_user = User(username=username, password=hashed_password)
db.session.add(new_user)
db.session.commit()
flash('注册成功,请登录', 'success')
return redirect(url_for('auth.login'))
return render_template('auth/register.html')
💡 注释:
Blueprint让路由逻辑独立于主应用,便于复用和测试。generate_password_hash保证密码安全存储,永远不要明文保存密码。
模板与静态资源管理
模板文件放在 app/templates/,静态资源放在 app/static/。
示例:app/templates/base.html(基础模板)
<!-- app/templates/base.html -->
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>{% block title %}我的 Flask 博客{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<header>
<h1>我的 Flask 博客</h1>
<nav>
<a href="{{ url_for('blog.index') }}">首页</a>
<a href="{{ url_for('auth.login') }}">登录</a>
<a href="{{ url_for('auth.register') }}">注册</a>
</nav>
</header>
<main>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</main>
</body>
</html>
💡 注释:
url_for是 Flask 的路由反向解析机制,避免硬编码 URL。get_flashed_messages用于显示提示信息,是 Flask 的内置功能。
启动脚本:run.py 的作用
最后,创建一个启动文件,让运行更清晰。
from app import create_app
import os
os.environ['FLASK_ENV'] = 'development'
app = create_app()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
运行命令:
python run.py
浏览器访问 http://127.0.0.1:5000,你就能看到你的项目已成功运行。
总结:构建可持续的 Flask 项目
一个清晰的 Flask 项目结构,不是形式主义,而是对代码质量的承诺。它让你在面对复杂需求时,依然能从容应对,而不是手忙脚乱。
从今天开始,不要再把 Flask 当作“脚本工具”使用。真正把它当作一个完整的 Web 框架来构建。遵循模块化、职责分离的原则,你的项目才能走得更远。
记住:代码的整洁度,决定了你的开发效率。一个良好的 Flask 项目结构,是你迈向专业开发的第一步。
最后提醒:项目中不要硬编码敏感信息(如数据库密码、API 密钥),务必使用
.env文件配合python-dotenv加载,确保安全。