Flask项目结构 #

一、项目结构概述 #

1.1 为什么需要良好的项目结构 #

优势 说明
可维护性 代码组织清晰,便于维护
可扩展性 易于添加新功能
可测试性 便于编写单元测试
团队协作 规范的结构便于团队开发
代码复用 模块化设计提高复用性

1.2 结构选择原则 #

  • 小型项目:简单结构,快速开发
  • 中型项目:模块化结构,便于扩展
  • 大型项目:完整的分层架构,团队协作

二、小型项目结构 #

2.1 单文件结构 #

适用于学习和小型项目:

text
myapp/
├── venv/
├── app.py              # 主应用文件
├── templates/          # 模板目录
│   └── index.html
├── static/             # 静态文件目录
│   ├── css/
│   │   └── style.css
│   └── js/
│       └── main.js
├── requirements.txt
└── .env

app.py:

python
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=True)

2.2 简单多文件结构 #

text
myapp/
├── venv/
├── app.py              # 应用入口
├── models.py           # 数据模型
├── views.py            # 视图函数
├── forms.py            # 表单类
├── templates/
│   ├── base.html
│   └── index.html
├── static/
│   ├── css/
│   └── js/
├── requirements.txt
└── .env

app.py:

python
from flask import Flask
from views import *

app = Flask(__name__)

if __name__ == '__main__':
    app.run(debug=True)

views.py:

python
from app import app
from flask import render_template

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/about')
def about():
    return render_template('about.html')

三、中型项目结构 #

3.1 包结构 #

推荐的中型项目结构:

text
myapp/
├── venv/
├── app/
│   ├── __init__.py         # 创建Flask应用
│   ├── models.py           # 数据模型
│   ├── views.py            # 视图函数
│   ├── forms.py            # 表单类
│   ├── templates/          # 模板目录
│   │   ├── base.html
│   │   ├── index.html
│   │   └── auth/
│   │       ├── login.html
│   │       └── register.html
│   └── static/             # 静态文件
│       ├── css/
│       ├── js/
│       └── images/
├── migrations/             # 数据库迁移文件
├── tests/                  # 测试文件
│   ├── __init__.py
│   ├── test_models.py
│   └── test_views.py
├── config.py               # 配置文件
├── requirements.txt
├── run.py                  # 启动脚本
└── .env

3.2 文件说明 #

app/init.py:

python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager

db = SQLAlchemy()
login_manager = LoginManager()

def create_app(config_name='default'):
    app = Flask(__name__)
    
    # 加载配置
    from config import config
    app.config.from_object(config[config_name])
    
    # 初始化扩展
    db.init_app(app)
    login_manager.init_app(app)
    
    # 注册蓝图
    from app.views import main
    app.register_blueprint(main)
    
    return app

config.py:

python
import os

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-secret-key')
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:///app.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class DevelopmentConfig(Config):
    DEBUG = True

class TestingConfig(Config):
    TESTING = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'

class ProductionConfig(Config):
    DEBUG = False

config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}

run.py:

python
import os
from app import create_app

app = create_app(os.getenv('FLASK_ENV', 'development'))

if __name__ == '__main__':
    app.run()

app/views.py:

python
from flask import Blueprint, render_template

main = Blueprint('main', __name__)

@main.route('/')
def index():
    return render_template('index.html')

@main.route('/about')
def about():
    return render_template('about.html')

四、大型项目结构 #

4.1 完整模块化结构 #

text
myapp/
├── venv/
├── app/
│   ├── __init__.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── user.py
│   │   ├── post.py
│   │   └── comment.py
│   ├── auth/                    # 认证模块
│   │   ├── __init__.py
│   │   ├── routes.py
│   │   ├── forms.py
│   │   └── templates/
│   │       ├── login.html
│   │       └── register.html
│   ├── main/                    # 主模块
│   │   ├── __init__.py
│   │   ├── routes.py
│   │   ├── forms.py
│   │   └── templates/
│   │       ├── index.html
│   │       └── about.html
│   ├── api/                     # API模块
│   │   ├── __init__.py
│   │   ├── users.py
│   │   └── posts.py
│   ├── static/
│   │   ├── css/
│   │   ├── js/
│   │   └── images/
│   ├── templates/
│   │   ├── base.html
│   │   └── macros/
│   │       └── forms.html
│   └── utils/
│       ├── __init__.py
│       ├── decorators.py
│       └── validators.py
├── migrations/
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   ├── test_models/
│   │   ├── test_user.py
│   │   └── test_post.py
│   └── test_routes/
│       ├── test_auth.py
│       └── test_main.py
├── config.py
├── requirements.txt
├── run.py
├── .env
├── .flaskenv
└── README.md

4.2 模块说明 #

app/init.py:

python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_mail import Mail
from flask_migrate import Migrate

db = SQLAlchemy()
login_manager = LoginManager()
mail = Mail()
migrate = Migrate()

def create_app(config_name='default'):
    app = Flask(__name__)
    
    from config import config
    app.config.from_object(config[config_name])
    
    # 初始化扩展
    db.init_app(app)
    login_manager.init_app(app)
    mail.init_app(app)
    migrate.init_app(app, db)
    
    # 注册蓝图
    from app.auth import auth as auth_blueprint
    from app.main import main as main_blueprint
    from app.api import api as api_blueprint
    
    app.register_blueprint(auth_blueprint, url_prefix='/auth')
    app.register_blueprint(main_blueprint)
    app.register_blueprint(api_blueprint, url_prefix='/api')
    
    return app

app/auth/init.py:

python
from flask import Blueprint

auth = Blueprint('auth', __name__)

from . import routes

app/auth/routes.py:

python
from flask import render_template, redirect, url_for, flash
from flask_login import login_user, logout_user
from . import auth
from .forms import LoginForm, RegistrationForm
from app.models.user import User
from app import db

@auth.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and user.verify_password(form.password.data):
            login_user(user)
            return redirect(url_for('main.index'))
        flash('Invalid email or password.')
    return render_template('auth/login.html', form=form)

@auth.route('/register', methods=['GET', 'POST'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User(
            email=form.email.data,
            username=form.username.data,
            password=form.password.data
        )
        db.session.add(user)
        db.session.commit()
        flash('Registration successful!')
        return redirect(url_for('auth.login'))
    return render_template('auth/register.html', form=form)

@auth.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('main.index'))

app/main/init.py:

python
from flask import Blueprint

main = Blueprint('main', __name__)

from . import routes

app/main/routes.py:

python
from flask import render_template
from . import main

@main.route('/')
def index():
    return render_template('index.html')

@main.route('/about')
def about():
    return render_template('about.html')

app/api/init.py:

python
from flask import Blueprint

api = Blueprint('api', __name__)

from . import users, posts

app/api/users.py:

python
from flask import jsonify, request
from . import api
from app.models.user import User

@api.route('/users', methods=['GET'])
def get_users():
    users = User.query.all()
    return jsonify([u.to_dict() for u in users])

@api.route('/users/<int:id>', methods=['GET'])
def get_user(id):
    user = User.query.get_or_404(id)
    return jsonify(user.to_dict())

五、蓝图详解 #

5.1 什么是蓝图 #

蓝图是Flask中组织代码的方式,类似于Django中的应用。它允许你将相关的视图、模板和静态文件组织在一起。

5.2 创建蓝图 #

python
from flask import Blueprint

# 创建蓝图
# 参数:蓝图名称、模块名、url前缀(可选)
auth = Blueprint('auth', __name__, url_prefix='/auth')

# 定义路由
@auth.route('/login')
def login():
    return '登录页面'

@auth.route('/register')
def register():
    return '注册页面'

5.3 注册蓝图 #

python
from flask import Flask
from auth import auth

app = Flask(__name__)

# 注册蓝图
app.register_blueprint(auth)

# 注册时指定url前缀
app.register_blueprint(auth, url_prefix='/user')

5.4 蓝图模板 #

蓝图可以有自己的模板目录:

text
app/
├── auth/
│   ├── __init__.py
│   ├── routes.py
│   └── templates/
│       └── auth/
│           ├── login.html
│           └── register.html
└── templates/
    └── base.html

在蓝图中使用模板:

python
@auth.route('/login')
def login():
    return render_template('auth/login.html')

5.5 蓝图静态文件 #

python
# 创建带有静态文件的蓝图
admin = Blueprint(
    'admin', 
    __name__,
    static_folder='static',
    static_url_path='/admin/static'
)

六、配置管理 #

6.1 配置类 #

python
import os
from datetime import timedelta

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard-to-guess-string'
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///app.db'
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    
    # Session配置
    PERMANENT_SESSION_LIFETIME = timedelta(hours=1)
    SESSION_COOKIE_SECURE = True
    SESSION_COOKIE_HTTPONLY = True
    
    # 邮件配置
    MAIL_SERVER = os.environ.get('MAIL_SERVER')
    MAIL_PORT = int(os.environ.get('MAIL_PORT') or 25)
    MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
    MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
    MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')

class DevelopmentConfig(Config):
    DEBUG = True
    SESSION_COOKIE_SECURE = False

class TestingConfig(Config):
    TESTING = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
    WTF_CSRF_ENABLED = False

class ProductionConfig(Config):
    DEBUG = False

config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}

6.2 使用配置 #

python
from flask import Flask
from config import config

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    return app

app = create_app('development')

七、工厂模式 #

7.1 什么是工厂模式 #

工厂模式是一种创建对象的设计模式,在Flask中用于延迟创建应用实例,便于测试和配置切换。

7.2 实现工厂模式 #

python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app(config_name='default'):
    app = Flask(__name__)
    
    # 加载配置
    from config import config
    app.config.from_object(config[config_name])
    
    # 初始化扩展
    db.init_app(app)
    
    # 注册蓝图
    from app.main import main
    app.register_blueprint(main)
    
    # 创建数据库表
    with app.app_context():
        db.create_all()
    
    return app

7.3 工厂模式的优势 #

优势 说明
多实例 可以创建多个应用实例
测试友好 每个测试使用独立配置
配置灵活 根据环境选择配置
延迟初始化 避免循环导入问题

八、最佳实践 #

8.1 目录命名规范 #

目录/文件 说明
app/ 应用主目录
models/ 数据模型
views/ 或 routes/ 视图函数
forms/ 表单类
templates/ 模板文件
static/ 静态文件
tests/ 测试文件
migrations/ 数据库迁移

8.2 文件命名规范 #

文件 说明
init.py 包初始化
models.py 数据模型
views.py / routes.py 视图函数
forms.py 表单类
config.py 配置文件
run.py 启动脚本

8.3 代码组织建议 #

  1. 模型与视图分离将模型定义放在models.py视图函数放在views.py
  2. 使用蓝图:按功能模块组织代码
  3. 配置分离:使用配置类管理不同环境配置
  4. 使用工厂模式:便于测试和多环境部署

九、总结 #

9.1 核心要点 #

要点 说明
结构选择 根据项目规模选择合适结构
蓝图使用 模块化组织代码
配置管理 使用配置类和环境变量
工厂模式 延迟创建应用实例

9.2 下一步 #

现在你已经了解了Flask项目结构,接下来让我们学习 路由基础,深入了解Flask的路由系统!

最后更新:2026-03-28