授课语音

项目框架搭建

在项目开发的初期,良好的项目框架能够确保后续开发的高效进行。本节将以 flask_blog 项目为例,讲解如何初始化一个基于 Flask 的博客项目,包括目录结构的设计、环境的配置以及基础文件的创建。


1. 项目初始化目标

通过本节内容,我们将实现以下目标:

  • 创建合理的目录结构,支持项目的模块化开发。
  • 配置虚拟环境和必要的依赖项。
  • 初始化 Flask 应用,确保项目具备基本运行能力。

2. 项目目录结构

在开发中,一个清晰的目录结构能帮助团队快速理解项目组织方式。flask_blog 项目目录结构如下:

flask_blog/
│
├── zhiliblog/            # 主应用目录
│   ├── blueprints/       # 各功能模块的蓝本目录
│   ├── core/             # 核心功能模块(如扩展初始化)
│   ├── static/           # 静态资源文件(CSS、JS、图片等)
│   ├── templates/        # HTML 模板文件
│   ├── __init__.py       # 工厂函数创建应用实例
│   ├── emails.py         # 邮件相关功能模块
│   ├── forms.py          # 表单相关逻辑
│   ├── lorem.py          # 数据填充(如虚拟数据生成)
│   ├── models.py         # 数据库模型定义
│   ├── settings.py       # 配置管理模块
│   └── utils.py          # 通用工具函数
│
├── logs/                 # 日志文件目录
├── uploads/              # 文件上传目录
├── venv/                 # 虚拟环境目录
├── .env                  # 环境变量文件
├── .gitignore            # Git 忽略规则
├── app.py                # 应用的入口文件
└── README.md             # 项目说明文档


3. 项目初始化流程

3.1 创建项目目录与初始化环境

步骤:

  1. 创建项目根目录 flask_blog
  2. 在项目根目录中创建子目录和必要的文件。
  3. 初始化 Python 虚拟环境,安装 Flask 和其他依赖。

代码案例:

# 创建项目根目录
mkdir flask_blog
cd flask_blog

# 创建子目录
mkdir logs uploads zhiliblog

# 创建空文件
touch .env .gitignore app.py README.md

# 进入主业务目录
cd zhiliblog

mkdir blueprints static templates core

# 创建空文件
touch __init__.py emails.py forms.py lorem.py models.py settings.py utils.py

# 初始化虚拟环境
python3 -m venv venv

# 激活虚拟环境(Linux/macOS)
source venv/bin/activate

# 激活虚拟环境(Windows)
venv\Scripts\activate

# 安装必要依赖
pip install flask flask-sqlalchemy flask-migrate python-dotenv

目录结构预览:

执行上述命令后,目录结构应与预期一致,空文件和子目录已创建完毕,建议用Pycharm打开项目进行开发,可以在Pycharm的terminal中输入命令。


3.2 配置虚拟环境和依赖

步骤:

  1. 在项目根目录创建 .env 文件,用于存储环境变量。
  2. 在项目中使用 python-dotenv 加载环境变量。
  3. 配置 Flask 项目基础依赖。

代码案例:

# .env 文件内容
# FLASK_CONFIG=production  # 正式环境打开
# SECRET_KEY=mysecretkey     # 项目秘钥
# MAIL_SERVER=smtp.example.com
# MAIL_USERNAME=example
# MAIL_PASSWORD=example-password
# settings.py
import os  # 操作系统相关模块,用于读取环境变量等
import sys  # 系统模块,用于检查平台信息
from pathlib import Path  # 文件路径模块,方便跨平台处理路径

# 定义项目的根目录
BASE_DIR = Path(__file__).resolve().parent.parent
# 根据操作系统定义 SQLite 数据库的 URI 前缀
SQLITE_PREFIX = 'sqlite:///' if sys.platform.startswith('win') else 'sqlite:////'


# 基础配置类,所有环境通用的配置
class BaseConfig:
    SECRET_KEY = os.getenv('SECRET_KEY', 'dev key')  # 加密密钥,默认使用 'dev key'

    DEBUG_TB_INTERCEPT_REDIRECTS = False  # 是否在调试工具条中拦截重定向,默认关闭
    DEBUG_TB_ENABLED = False  # 是否启用调试工具条,默认关闭

    SQLALCHEMY_RECORD_QUERIES = True  # 启用查询记录,用于性能监控

    CKEDITOR_ENABLE_CSRF = True  # 启用 CKEditor 的 CSRF 保护
    CKEDITOR_FILE_UPLOADER = 'admin.upload_image'  # 指定 CKEditor 文件上传的视图函数

    # 邮件服务器配置
    MAIL_SERVER = os.getenv('MAIL_SERVER')  # 邮件服务器地址
    MAIL_PORT = 587  # 邮件服务器端口,默认 587(TLS)
    MAIL_USE_TLS = True  # 启用 TLS 加密
    MAIL_USERNAME = os.getenv('MAIL_USERNAME')  # 邮件服务器用户名
    MAIL_PASSWORD = os.getenv('MAIL_PASSWORD')  # 邮件服务器密码
    MAIL_DEFAULT_SENDER = f'知理编程 <{MAIL_USERNAME}>'  # 默认发件人

    # 博客相关配置
    ZHILIBLOG_ADMIN_EMAIL = os.getenv('ZHILIBLOG_ADMIN_EMAIL', 'zhilitech@163.com')  # 管理员邮箱
    ZHILIBLOG_POST_PER_PAGE = 10  # 每页文章数
    ZHILIBLOG_MANAGE_POST_PER_PAGE = 15  # 后台管理每页文章数
    ZHILIBLOG_COMMENT_PER_PAGE = 15  # 每页评论数
    ZHILIBLOG_THEMES = {'default': 'Default', 'bluelog': 'Bluelog'}  # 主题选项
    ZHILIBLOG_SLOW_QUERY_THRESHOLD = 1  # 慢查询阈值(秒)

    # 文件上传相关配置
    ZHILIBLOG_UPLOAD_PATH = os.getenv('ZHILIBLOG_UPLOAD_PATH', BASE_DIR / 'uploads')  # 上传文件保存路径
    ZHILIBLOG_ALLOWED_IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif']  # 允许的图片扩展名
    ZHILIBLOG_LOGGING_PATH = os.getenv('ZHILIBLOG_LOGGING_PATH', BASE_DIR / 'logs/info.log')  # 日志文件路径

    # 错误报告配置
    ZHILIBLOG_ERROR_EMAIL_SUBJECT = '[知理编程] Application Error'  # 错误邮件主题


# 开发环境配置
class DevelopmentConfig(BaseConfig):
    SQLALCHEMY_DATABASE_URI = SQLITE_PREFIX + str(BASE_DIR / 'data-dev.db')  # 使用本地 SQLite 数据库文件


# 测试环境配置
class TestingConfig(BaseConfig):
    TESTING = True  # 启用测试模式
    WTF_CSRF_ENABLED = False  # 禁用 CSRF 保护(测试环境不需要)
    SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'  # 使用内存数据库,便于测试


# 生产环境配置
class ProductionConfig(BaseConfig):
    SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL', SQLITE_PREFIX + str(BASE_DIR / 'data.db'))  # 使用环境变量指定数据库 URI,默认使用 SQLite 数据库文件


# 配置映射字典,便于动态选择配置
config = {
    'development': DevelopmentConfig,  # 开发环境配置
    'testing': TestingConfig,  # 测试环境配置
    'production': ProductionConfig  # 生产环境配置
}


3.3 创建工厂函数

使用工厂函数模式初始化 Flask 应用,便于进行模块化开发和配置管理。

代码案例:

# __init__.py
# 导入Flask框架的核心类
from flask import Flask

from zhiliblog.core.extensions import (  # 导入扩展实例
    bootstrap, ckeditor, csrf, db, login_manager, mail, migrate, toolbar
)
# 导入项目的配置
from zhiliblog.settings import config


def create_app(config_name):
    # 创建Flask应用实例,指定应用名、模板目录和静态文件目录
    app = Flask('zhiliblog', template_folder='zhiliblog/templates', static_folder='zhiliblog/static')
    # 加载配置,根据传入的配置名称选择对应配置
    app.config.from_object(config[config_name])

    
    # 初始化扩展
    bootstrap.init_app(app)  # 初始化Bootstrap框架
    db.init_app(app)  # 初始化数据库
    login_manager.init_app(app)  # 初始化用户登录管理
    csrf.init_app(app)  # 初始化CSRF保护
    ckeditor.init_app(app)  # 初始化富文本编辑器
    mail.init_app(app)  # 初始化邮件发送
    toolbar.init_app(app)  # 初始化调试工具条
    migrate.init_app(app, db)  # 初始化数据库迁移工具


    # 返回创建好的应用实例
    return app

core核心中使用extensions.py管理所有扩展功能,需要安装依赖

pip install flask_ckeditor flask_debugtoolbar flask_login flask_mailman flask_wtf Bootstrap-Flask

代码示例

# extensions.py
from flask_bootstrap import Bootstrap5
from flask_ckeditor import CKEditor
from flask_debugtoolbar import DebugToolbarExtension
from flask_login import LoginManager
from flask_mailman import Mail
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import CSRFProtect
from sqlalchemy import MetaData
from sqlalchemy.orm import DeclarativeBase


# 基类,继承自DeclarativeBase,用于定义所有数据库模型
class Base(DeclarativeBase):
    metadata = MetaData(
        naming_convention={
            'ix': 'ix_%(column_0_label)s',  # 索引命名规则
            'uq': 'uq_%(table_name)s_%(column_0_name)s',  # 唯一约束命名规则
            'ck': 'ck_%(table_name)s_%(constraint_name)s',  # 检查约束命名规则
            'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s',  # 外键约束命名规则
            'pk': 'pk_%(table_name)s',  # 主键命名规则
        }
    )


# 初始化Flask扩展
bootstrap = Bootstrap5()  # 用于Bootstrap 5前端框架的集成
db = SQLAlchemy(model_class=Base)  # SQLAlchemy扩展,基于Base类的数据库模型
login_manager = LoginManager()  # 用户认证管理
csrf = CSRFProtect()  # CSRF保护
ckeditor = CKEditor()  # 富文本编辑器
mail = Mail()  # 邮件功能
toolbar = DebugToolbarExtension()  # 调试工具栏
migrate = Migrate()  # 数据库迁移


3.4 配置 Git 忽略文件

确保虚拟环境目录和敏感文件不会被上传到代码库中。

代码案例:

# .gitignore 文件内容
venv/
*.pyc
__pycache__/
.env

3.5 项目入口文件

创建项目入口文件 app.py,用于运行 Flask 应用。

代码案例:

# app.py

# 导入必要的模块
import os  # 操作系统相关功能模块
from pathlib import Path  # 处理路径的模块
from dotenv import load_dotenv  # 用于加载.env文件中的环境变量

# 获取当前脚本所在目录下的.env文件路径
dotenv_path = Path(__file__).resolve().parent / '.env'
if dotenv_path.exists():  # 如果.env文件存在
    load_dotenv(dotenv_path)  # 加载.env文件中的环境变量

# 导入项目中定义的create_app函数,用于创建Flask应用实例
from zhiliblog import create_app

# 从环境变量中获取FLASK_CONFIG配置名称,默认为'development'
config_name = os.getenv('FLASK_CONFIG', 'development')
# 创建Flask应用实例,传入配置名称
app = create_app(config_name)


3.6 初始化数据库

配置完成后,运行以下命令初始化数据库:

# 创建迁移文件夹
flask db init

# 创建迁移脚本
flask db migrate -m "Initial migration"

# 应用迁移到数据库
flask db upgrade

4. 总结

通过本节学习,我们完成了 flask_blog 项目的基本初始化,包括:

  • 创建合理的目录结构。
  • 配置虚拟环境与依赖。
  • 使用工厂函数初始化 Flask 应用。
  • 配置 Git 忽略规则与数据库迁移。

这些内容为后续功能开发打下了坚实的基础。

去1:1私密咨询

系列课程: