SQLModel实战项目开发
本文详细介绍了SQLModel在实际项目开发中的全面应用,包括项目架构设计与模块划分、数据库迁移与版本控制、测试策略与质量保证,以及部署与生产环境配置。文章通过核心模块架构、迁移工作流程、测试覆盖率管理和生产环境数据库选择等多个维度,系统阐述了SQLModel的高效使用方法和最佳实践,为开发者提供了从开发到部署的完整解决方案。
项目架构设计与模块划分
SQLModel作为一个现代化的Python ORM库,其架构设计体现了模块化、可扩展性和兼容性的核心理念。项目采用分层架构设计,将核心功能划分为多个独立的模块,每个模块都有明确的职责边界。
核心模块架构
SQLModel的模块架构可以分为以下几个主要层次:
主要模块功能详解
1. 核心模块 (main.py)
核心模块是SQLModel的心脏,包含了主要的模型定义、字段处理和元类机制:
# SQLModel核心类定义
class SQLModel(BaseModel, metaclass=SQLModelMetaclass):
"""结合Pydantic和SQLAlchemy的核心模型类"""
# 表配置元数据
__tablename__: ClassVar[Optional[str]]
__table_args__: ClassVar[Dict[str, Any]]
# 数据库操作方法
def save(self, session: Session) -> None:
"""保存对象到数据库"""
session.add(self)
session.commit()
核心模块的主要职责包括:
- 模型类的定义和元类处理
- 字段验证和类型转换
- 数据库表元数据生成
- Pydantic和SQLAlchemy的桥接
2. ORM模块 (orm/)
ORM模块负责会话管理和对象关系映射:
| 子模块 | 功能描述 | 主要类/函数 |
|---|---|---|
| session.py | 数据库会话管理 | Session 类 |
| init.py | ORM模块导出 | 会话相关功能 |
# 会话管理示例
from sqlmodel import Session, create_engine
engine = create_engine("sqlite:///database.db")
with Session(engine) as session:
# 执行查询操作
heroes = session.exec(select(Hero)).all()
# 执行更新操作
session.add(new_hero)
session.commit()
3. SQL表达式模块 (sql/)
SQL表达式模块提供了类型安全的SQL查询构建功能:
该模块包含以下关键文件:
_expression_select_gen.py- 生成类型安全的select语句_expression_select_cls.py- select语句的类方法实现expression.py- SQL表达式构建函数sqltypes.py- 自定义SQL类型定义
4. 类型系统模块
类型系统模块负责字段定义和类型验证:
# 字段定义示例
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str = Field(max_length=100, index=True)
secret_name: str
age: Optional[int] = Field(default=None, ge=0, le=200)
created_at: datetime = Field(default_factory=datetime.now)
# 关系字段
team_id: Optional[int] = Field(foreign_key="team.id")
team: Optional["Team"] = Relationship(back_populates="heroes")
字段类型支持的功能包括:
- 主键和外键约束
- 索引和唯一约束
- 默认值和自动生成
- 数据验证规则(范围、长度等)
- 关系映射配置
5. 兼容性模块 (_compat.py)
兼容性模块确保SQLModel在不同版本的Pydantic和Python环境中的稳定运行:
# 兼容性处理示例
def get_config_value(
*, model: InstanceOrType["SQLModel"], parameter: str, default: Any = None
) -> Any:
"""获取模型配置值,处理不同Pydantic版本的差异"""
if hasattr(model, "model_config"):
# Pydantic v2
return getattr(model.model_config, parameter, default)
else:
# Pydantic v1
return getattr(model.Config, parameter, default)
模块间的协作关系
SQLModel的模块间通过清晰的接口进行协作:
设计模式应用
SQLModel在架构设计中应用了多种设计模式:
- 桥接模式 - 连接Pydantic和SQLAlchemy两个不同的抽象
- 工厂模式 - 字段和关系的动态创建
- 装饰器模式 - 通过Field和Relationship装饰器增强字段功能
- 元类编程 - 在类创建时动态修改类定义
扩展性设计
项目的扩展性体现在以下几个方面:
- 插件系统:通过ext模块支持异步操作等扩展
- 类型系统:支持自定义SQL类型和字段验证器
- 查询构建:可扩展的SQL表达式构建器
- 会话管理:支持不同的数据库连接池和会话策略
这种模块化的架构设计使得SQLModel既保持了代码的清晰性,又提供了充分的扩展空间,开发者可以根据需要选择使用特定模块的功能,或者通过扩展机制添加自定义功能。
数据库迁移与版本控制
在现代应用开发中,数据库模式(Schema)的变更管理是至关重要的环节。随着业务需求的不断变化,数据库结构也需要相应地进行调整。SQLModel 作为基于 SQLAlchemy 的 ORM 框架,提供了强大的数据库迁移和版本控制能力。
数据库迁移的基本概念
数据库迁移是指将数据库从一个版本升级到另一个版本的过程,包括创建新表、修改表结构、添加索引、变更约束等操作。SQLModel 通过 SQLAlchemy 的元数据管理功能,结合 Alembic 迁移工具,实现了完整的数据库版本控制解决方案。
迁移工作流程
使用 SQLModel.metadata 进行模式管理
SQLModel 提供了 SQLModel.metadata 对象来管理所有表模型的元数据。通过这个统一的元数据接口,我们可以轻松地进行数据库模式的创建和更新。
创建初始数据库模式
from sqlmodel import SQLModel, create_engine
from myapp.models import User, Post, Comment
# 创建数据库引擎
engine = create_engine("sqlite:///app.db")
# 创建所有表
SQLModel.metadata.create_all(engine)
表结构变更检测机制
当模型定义发生变化时,SQLModel 能够自动检测到这些变更:
class User(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
username: str = Field(index=True, unique=True)
email: str = Field(unique=True)
# 新增字段
phone: str | None = Field(default=None, max_length=20)
# 修改字段类型
created_at: datetime = Field(default_factory=datetime.now)
Alembic 迁移工具集成
虽然 SQLModel 本身不包含迁移工具,但它与 Alembic 完美集成,提供了强大的数据库版本控制能力。
初始化 Alembic 环境
# 安装 Alembic
pip install alembic
# 初始化迁移环境
alembic init migrations
配置 Alembic 使用 SQLModel
在 alembic.ini 中配置数据库连接:
# alembic.ini
sqlalchemy.url = sqlite:///app.db
在 env.py 中导入 SQLModel 模型:
# migrations/env.py
from myapp.models import SQLModel
from myapp.database import engine
target_metadata = SQLModel.metadata
生成迁移脚本
# 自动生成迁移脚本
alembic revision --autogenerate -m "添加用户手机号字段"
迁移脚本示例
# migrations/versions/001_add_user_phone.py
from alembic import op
import sqlalchemy as sa
def upgrade():
# 添加新字段
op.add_column('user', sa.Column('phone', sa.String(length=20), nullable=True))
# 创建索引
op.create_index(op.f('ix_user_phone'), 'user', ['phone'], unique=False)
def downgrade():
# 回滚操作
op.drop_index(op.f('ix_user_phone'), table_name='user')
op.drop_column('user', 'phone')
迁移策略最佳实践
1. 增量式迁移
采用小步快跑的方式,每次只进行最小化的变更:
# 不良实践:一次性大量变更
class User(SQLModel, table=True):
# 同时修改多个字段和约束
id: int = Field(primary_key=True)
username: str = Field(unique=True, index=True)
email: str = Field(unique=True)
phone: str
address: str
# ... 很多新字段
# 良好实践:分步迁移
# 第一次迁移:添加基础字段
# 第二次迁移:添加手机号字段
# 第三次迁移:添加地址字段
2. 数据迁移安全性
确保迁移过程中的数据完整性:
def upgrade():
# 先添加允许为空的字段
op.add_column('user', sa.Column('phone', sa.String(20), nullable=True))
# 数据迁移:为现有用户设置默认值
op.execute("UPDATE user SET phone = '未设置' WHERE phone IS NULL")
# 然后再设置为非空
op.alter_column('user', 'phone', nullable=False)
3. 回滚策略
为每个升级操作提供完整的回滚方案:
def downgrade():
# 删除索引
op.drop_index('ix_user_phone', table_name='user')
# 删除字段
op.drop_column('user', 'phone')
# 如果有数据需要恢复,在这里处理
版本控制工作流
开发环境迁移流程
生产环境部署流程
常见迁移场景处理
1. 字段重命名
def upgrade():
# 先添加新字段
op.add_column('user', sa.Column('email_address', sa.String(), nullable=True))
# 迁移数据
op.execute('UPDATE user SET email_address = email')
# 删除旧字段
op.drop_column('user', 'email')
# 重命名新字段
op.alter_column('user', 'email_address', new_column_name='email')
def downgrade():
op.add_column('user', sa.Column('email', sa.String(), nullable=True))
op.execute('UPDATE user SET email = email_address')
op.drop_column('user', 'email_address')
2. 修改字段类型
def upgrade():
# 创建临时字段
op.add_column('user', sa.Column('age_temp', sa.Integer(), nullable=True))
# 迁移并转换数据
op.execute('UPDATE user SET age_temp = CAST(age AS INTEGER)')
# 删除旧字段
op.drop_column('user', 'age')
# 重命名临时字段
op.alter_column('user', 'age_temp', new_column_name='age')
def downgrade():
op.add_column('user', sa.Column('age_old', sa.String(), nullable=True))
op.execute('UPDATE user SET age_old = CAST(age AS TEXT)')
op.drop_column('user', 'age')
op.alter_column('user', 'age_old', new_column_name='age')
3. 添加复杂约束
def upgrade():
# 添加检查约束
op.create_check_constraint(
'ck_user_age_positive',
'user',
'age >= 0'
)
# 添加外键约束
op.create_foreign_key(
'fk_post_author',
'post', 'user',
['author_id'], ['id']
)
def downgrade():
op.drop_constraint('ck_user_age_positive', 'user')
op.drop_constraint('fk_post_author', 'post')
迁移测试策略
为确保迁移的安全性,必须建立完整的测试体系:
单元测试示例
import pytest
from alembic.command import upgrade, downgrade
from alembic.config import Config
def test_migrations():
# 加载 Alembic 配置
alembic_cfg = Config("alembic.ini")
# 测试升级
upgrade(alembic_cfg, "head")
# 验证升级结果
# ... 检查数据库结构
# 测试回滚
downgrade(alembic_cfg, "base")
# 验证回滚结果
# ... 检查数据库结构
# 再次升级确保一致性
upgrade(alembic_cfg, "head")
数据一致性验证
def verify_migration_data():
# 验证数据迁移的正确性
with engine.connect() as conn:
result = conn.execute(text("SELECT COUNT(*) FROM user WHERE phone IS NULL"))
null_count = result.scalar()
assert null_count == 0, "存在未迁移的手机号数据"
性能优化建议
大规模数据迁移
对于包含大量数据的表,迁移时需要特别注意性能:
def upgrade():
# 分批处理大数据量表
batch_size = 1000
total_count = get_user_count()
for offset in range(0, total_count, batch_size):
op.execute(f"""
UPDATE user
SET phone = 'default'
WHERE id IN (
SELECT id FROM user
WHERE phone IS NULL
LIMIT {batch_size} OFFSET {offset}
)
""")
索引管理优化
在迁移过程中合理管理索引可以显著提升性能:
def upgrade():
# 先删除索引以提高写入性能
op.drop_index('ix_user_email', table_name='user')
# 执行数据迁移操作
op.add_column('user', sa.Column('new_field', sa.String()))
# 最后重新创建索引
op.create_index('ix_user_email', 'user', ['email'])
通过上述方法和策略,SQLModel 为数据库迁移和版本控制提供了完整而强大的解决方案,确保数据库结构的变更能够安全、高效地进行。
测试策略与质量保证
SQLModel项目采用了全面而严谨的测试策略,确保代码质量和稳定性。项目维护着高达97%的测试覆盖率,并持续向100%的目标迈进。测试体系涵盖了单元测试、集成测试、文档测试等多个层面,为开发者提供了可靠的代码保障。
测试架构与工具链
SQLModel的测试架构基于现代化的Python测试工具链,主要包含以下核心组件:
| 工具/组件 | 版本要求 | 主要用途 |
|---|---|---|
| pytest | 最新稳定版 | 测试框架和运行器 |
| coverage | >=6.2,<8.0 | 代码覆盖率分析 |
| SQLite | 内存数据库 | 快速单元测试 |
| SQLAlchemy | >=2.0.14,<2.1.0 | ORM功能测试 |
| Pydantic | >=1.10.13,<3.0.0 | 数据验证测试 |
测试配置通过pyproject.toml文件进行集中管理,确保测试环境的一致性和可重复性。
分层测试策略
SQLModel采用分层测试策略,每个层次都有明确的测试目标和方法:
1. 单元测试层
单元测试专注于单个函数或类的独立功能验证,使用内存SQLite数据库确保测试速度。
def test_should_allow_duplicate_row_if_unique_constraint_is_not_passed(clear_sqlmodel):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Deadpond", secret_name="Dive Wilson")
engine = create_engine("sqlite://")
SQLModel.metadata.create_all(engine)
# 测试重复数据插入行为
with Session(engine) as session:
session.add(hero_1)
session.commit()
with Session(engine) as session:
session.add(hero_2)
session.commit()
# 验证结果
with Session(engine) as session:
heroes = session.exec(select(Hero)).all()
assert len(heroes) == 2
assert heroes[0].name == heroes[1].name
2. 集成测试层
集成测试验证SQLModel与SQLAlchemy、Pydantic的兼容性和协同工作能力:
def test_sa_relationship_property(clear_sqlmodel):
"""测试SQLAlchemy关系属性兼容性"""
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str = Field(unique=True)
heroes: List["Hero"] = Relationship(
sa_relationship=RelationshipProperty("Hero", back_populates="team")
)
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str = Field(unique=True)
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(
sa_relationship=RelationshipProperty("Team", back_populates="heroes")
)
# 测试关系映射功能
team_preventers = Team(name="Preventers")
hero_rusty_man = Hero(name="Rusty-Man", team=team_preventers)
engine = create_engine("sqlite://", echo=True)
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
session.add(hero_rusty_man)
session.commit()
session.refresh(hero_rusty_man)
# 验证关系属性正常工作
assert hero_rusty_man.team
assert hero_rusty_man.team.name == "Preventers"
3. 文档测试层
文档测试确保所有教程示例代码的正确性,通过覆盖率工具验证文档代码的执行:
def test_create_db_and_table(cov_tmp_path: Path):
module = "docs_src.tutorial.create_db_and_table.tutorial001"
result = coverage_run(module=module, cwd=cov_tmp_path)
# 验证SQL语句生成正确
assert "BEGIN" in result.stdout
assert 'PRAGMA main.table_info("hero")' in result.stdout
assert "CREATE TABLE hero (" in result.stdout
assert "id INTEGER NOT NULL," in result.stdout
assert "name VARCHAR NOT NULL," in result.stdout
assert "secret_name VARCHAR NOT NULL," in result.stdout
assert "age INTEGER," in result.stdout
assert "PRIMARY KEY (id)" in result.stdout
assert ")" in result.stdout
assert "COMMIT" in result.stdout
测试覆盖率管理
SQLModel使用coverage.py进行详细的代码覆盖率分析,配置包括:
[tool.coverage.run]
parallel = true
data_file = "coverage/.coverage"
source = [
"docs_src",
"tests",
"sqlmodel"
]
context = '${CONTEXT}'
dynamic_context = "test_function"
[tool.coverage.report]
show_missing = true
sort = "-Cover"
exclude_lines = [
"pragma: no cover",
"@overload",
'if __name__ == "__main__":',
"if TYPE_CHECKING:",
]
覆盖率报告通过自动化脚本生成:
#!/usr/bin/env bash
set -e
set -x
coverage run -m pytest tests
coverage combine
coverage report
coverage html
多版本兼容性测试
SQLModel支持Python 3.8+版本,并通过条件标记处理不同版本的测试需求:
needs_pydanticv2 = pytest.mark.skipif(not IS_PYDANTIC_V2, reason="requires Pydantic v2")
needs_pydanticv1 = pytest.mark.skipif(IS_PYDANTIC_V2, reason="requires Pydantic v1")
needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+")
needs_py310 = pytest.mark.skipif(sys.version_info < (3, 10), reason="requires python3.10+")
测试数据管理
测试使用内存数据库和临时文件确保测试隔离性:
@pytest.fixture(autouse=True)
def clear_sqlmodel() -> Any:
# 清理元数据中的表
SQLModel.metadata.clear()
# 清理注册表中的模型,避免警告
default_registry.dispose()
yield
SQLModel.metadata.clear()
default_registry.dispose()
错误处理和边界测试
SQLModel包含大量错误场景和边界条件的测试:
def test_should_raise_exception_when_try_to_duplicate_row_if_unique_constraint_is_true(clear_sqlmodel):
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str = Field(unique=True)
age: Optional[int] = None
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Deadpond", secret_name="Dive Wilson")
engine = create_engine("sqlite://")
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
session.add(hero_1)
session.commit()
# 测试唯一约束违规异常
with pytest.raises(IntegrityError):
with Session(engine) as session:
session.add(hero_2)
session.commit()
持续集成与质量门禁
项目通过GitHub Actions实现持续集成,每次提交都会自动运行完整的测试套件:
测试策略的核心目标是确保SQLModel在不同Python版本、不同Pydantic版本以及不同数据库后端的兼容性和稳定性。通过严格的测试覆盖率和自动化测试流程,为开发者提供可靠、高质量的ORM解决方案。
部署与生产环境配置
在开发阶段使用SQLite数据库进行快速原型开发是很方便的,但当应用准备投入生产环境时,我们需要考虑更健壮、可扩展的数据库解决方案。本节将详细介绍如何将SQLModel应用从开发环境迁移到生产环境,包括数据库选择、连接池配置、环境变量管理、SSL加密等关键配置。
生产环境数据库选择
生产环境通常需要选择更强大的数据库系统,以下是常见的选择:
| 数据库类型 | 连接字符串格式 | 适用场景 | 特点 |
|---|---|---|---|
| PostgreSQL | postgresql://user:pass@host:port/dbname | 企业级应用 | ACID兼容,功能丰富,扩展性强 |
| MySQL | mysql://user:pass@host:port/dbname | Web应用 | 性能优秀,社区活跃 |
| SQLite | sqlite:///database.db | 开发/测试 | 轻量级,文件存储,无需服务器 |
环境变量配置管理
在生产环境中,硬编码数据库连接字符串是不安全的。推荐使用环境变量来管理配置:
import os
from sqlmodel import create_engine, SQLModel, Session
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# 从环境变量获取数据库配置
DATABASE_URL = os.getenv("DATABASE_URL")
if not DATABASE_URL:
raise ValueError("DATABASE_URL environment variable is required")
# 创建数据库引擎
engine = create_engine(
DATABASE_URL,
pool_size=20, # 连接池大小
max_overflow=10, # 最大溢出连接数
pool_timeout=30, # 连接超时时间(秒)
pool_recycle=1800, # 连接回收时间(秒)
echo=False # 生产环境关闭SQL日志
)
连接池优化配置
生产环境中的数据库连接池配置至关重要,以下是一些推荐的最佳实践:
from sqlmodel import create_engine
import os
def create_production_engine():
"""创建生产环境数据库引擎"""
database_url = os.getenv("DATABASE_URL")
# PostgreSQL连接池配置
engine = create_engine(
database_url,
# 连接池配置
pool_size=int(os.getenv("DB_POOL_SIZE", "20")),
max_overflow=int(os.getenv("DB_MAX_OVERFLOW", "10")),
pool_timeout=int(os.getenv("DB_POOL_TIMEOUT", "30")),
pool_recycle=int(os.getenv("DB_POOL_RECYCLE", "1800")),
pool_pre_ping=bool(os.getenv("DB_POOL_PRE_PING", "True")),
# 性能优化
echo=bool(os.getenv("DB_ECHO", "False")),
hide_parameters=bool(os.getenv("DB_HIDE_PARAMETERS", "True")),
# SSL配置(如果使用云数据库)
connect_args={
"ssl": os.getenv("DB_SSL_MODE", "prefer")
} if "postgresql" in database_url else {}
)
return engine
SSL/TLS加密配置
对于生产环境,特别是云数据库服务,启用SSL加密是必须的:
import ssl
from sqlmodel import create_engine
def create_secure_engine():
"""创建安全的数据库连接"""
database_url = os.getenv("DATABASE_URL")
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = True
ssl_context.verify_mode = ssl.CERT_REQUIRED
connect_args = {
"ssl": ssl_context,
"connect_timeout": 10, # 连接超时10秒
}
engine = create_engine(
database_url,
connect_args=connect_args,
pool_size=20,
pool_recycle=1800,
pool_pre_ping=True
)
return engine
多环境配置管理
使用不同的配置文件来管理开发、测试和生产环境:
# config.py
import os
from enum import Enum
class Environment(Enum):
DEVELOPMENT = "development"
TESTING = "testing"
PRODUCTION = "production"
def get_environment():
"""获取当前环境"""
env = os.getenv("APP_ENV", "development")
return Environment(env)
def get_database_config():
"""根据环境获取数据库配置"""
env = get_environment()
configs = {
Environment.DEVELOPMENT: {
"url": "sqlite:///dev.db",
"echo": True,
"pool_size": 5
},
Environment.TESTING: {
"url": "sqlite:///test.db",
"echo": False,
"pool_size": 10
},
Environment.PRODUCTION: {
"url": os.getenv("DATABASE_URL"),
"echo": False,
"pool_size": 20,
"pool_recycle": 1800,
"pool_pre_ping": True
}
}
return configs[env]
# 使用配置创建引擎
from sqlmodel import create_engine
config = get_database_config()
engine = create_engine(config["url"], **{k: v for k, v in config.items() if k != "url"})
数据库迁移策略
生产环境的数据迁移需要谨慎处理,推荐使用Alembic进行数据库版本管理:
# alembic/env.py
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
from myapp.models import SQLModel # 导入你的模型
# 配置Alembic
config = context.config
fileConfig(config.config_file_name)
target_metadata = SQLModel.metadata
def run_migrations_online():
"""运行在线迁移"""
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
compare_type=True,
compare_server_default=True
)
with context.begin_transaction():
context.run_migrations()
run_migrations_online()
健康检查与监控
生产环境需要监控数据库连接的健康状态:
import time
from sqlmodel import Session, select
from sqlalchemy import text
def check_database_health(engine):
"""检查数据库健康状态"""
try:
with Session(engine) as session:
# 执行简单查询测试连接
result = session.exec(text("SELECT 1"))
result.scalar()
return True
except Exception as e:
print(f"Database health check failed: {e}")
return False
def monitor_database_connections(engine):
"""监控数据库连接状态"""
pool = engine.pool
print(f"Current connections: {pool.checkedin()}")
print(f"Connections in use: {pool.checkedout()}")
print(f"Total connections: {pool.size()}")
容器化部署配置
对于Docker容器化部署,需要相应的配置:
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 设置环境变量
ENV APP_ENV=production
ENV DATABASE_URL=postgresql://user:pass@db:5432/mydb
ENV DB_POOL_SIZE=20
ENV DB_POOL_TIMEOUT=30
# 运行应用
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:password@db:5432/mydb
- DB_POOL_SIZE=20
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
性能优化建议
通过以上配置和最佳实践,你的SQLModel应用将能够在生产环境中稳定运行,具备良好的性能、安全性和可维护性。记得在生产部署前进行充分的负载测试和压力测试,确保数据库配置能够满足实际业务需求。
总结
通过本文的全面介绍,我们深入了解了SQLModel在实际项目开发中的完整生命周期管理。从模块化的架构设计到严谨的数据库迁移策略,从全面的测试覆盖到生产环境的优化配置,SQLModel展现出了强大的功能和良好的扩展性。这些最佳实践不仅确保了应用的稳定性和性能,也为团队协作和项目维护提供了坚实基础,是构建高质量Python应用的宝贵参考。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



