Alembic 和 SQLAlchemy 的最佳实践
积累知识,胜过积蓄金银!毕竟在文章开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《Alembic 和 SQLAlchemy 的最佳实践》,就带大家讲解一下知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~
在本文中,我将简要介绍一些最佳实践,这些最佳实践在使用 alembic 和 sqlalchemy 时帮助保持项目有序、简化数据库维护并防止常见陷阱。这些技巧不止一次地让我摆脱了麻烦。以下是我们将介绍的内容:
- 命名约定
- 按日期对迁移进行排序
- 表、列和迁移注释
- 无模型迁移中的数据处理
- 迁移测试(楼梯测试)
- 运行迁移的服务
- 对模型使用 mixins
1. 命名约定
sqlalchemy 允许您设置命名约定,在生成迁移时自动应用于所有表和约束。这使您无需手动命名索引、外键和其他约束,从而使数据库结构可预测且一致。
要在新项目中进行设置,请向基类添加约定,以便 alembic 将自动使用所需的命名格式。以下是在大多数情况下都有效的约定示例:
from sqlalchemy import metadata
from sqlalchemy.orm import declarativebase
convention = {
'all_column_names': lambda constraint, table: '_'.join(
[column.name for column in constraint.columns.values()]
),
'ix': 'ix__%(table_name)s__%(all_column_names)s',
'uq': 'uq__%(table_name)s__%(all_column_names)s',
'ck': 'ck__%(table_name)s__%(constraint_name)s',
'fk': 'fk__%(table_name)s__%(all_column_names)s__%(referred_table_name)s',
'pk': 'pk__%(table_name)s',
}
class basemodel(declarativebase):
metadata = metadata(naming_convention=convention)
2. 按日期对迁移进行排序
alembic 迁移文件名通常以修订标签开头,这可以使目录中的迁移顺序显得随机。有时按时间顺序排列它们很有用。
alembic 允许使用 file_template 设置在 alembic.ini 文件中自定义迁移文件名模板。以下是两种方便的命名格式,可让迁移保持井井有条:
- 基于日期:
file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
- 基于 unix 时间戳:
file_template = %%(epoch)d_%%(rev)s_%%(slug)s
在文件名中使用日期或 unix 时间戳可以使迁移保持井井有条,使导航更容易。我更喜欢使用 unix 时间戳,下一节将提供一个示例。
3. 表和迁移的注释
对于在团队中工作的人来说,注释属性是一个很好的做法。对于 sqlalchemy 模型,请考虑直接向列和表添加注释,而不是依赖文档字符串。这样,注释在代码和数据库中都可用,使 dba 或分析师更容易理解表和字段的用途。
class event(basemodel):
__table_args__ = {'comment': 'system (service) event'}
id: mapped[uuid.uuid] = mapped_column(
uuid(as_uuid=true),
primary_key=true,
comment='event id - pk',
)
service_id: mapped[int] = mapped_column(
sa.integer,
sa.foreignkey(
f'{integrationservicemodel.__tablename__}.id',
ondelete='cascade',
),
nullable=false,
comment='fk to integration service that owns the event',
)
name: mapped[str] = mapped_column(
sa.string(256), nullable=false, comment='event name'
)
为迁移添加注释也很有帮助,以便更容易在文件系统中找到它们。生成迁移时可以使用 -m
1728372261_c0a05e0cd317_add_integration_service.py 1728372272_a1b4c9df789d_add_user.py 1728372283_f32d57aa1234_update_order_status.py 1728372294_9c8e7ab45e11_create_payment.py 1728372305_bef657cd9342_remove_old_column_from_users.py
4. 避免在迁移中使用模型
模型通常用于数据操作,例如将数据从一个表传输到另一个表或修改列值。但是,如果模型在创建迁移后发生更改,则在迁移中使用 orm 模型可能会导致问题。在这种情况下,基于旧模型的迁移在执行时将会中断,因为数据库架构可能不再与当前模型匹配。
迁移应该是静态的并且独立于模型的当前状态,以确保无论代码如何更改都能正确执行。以下是避免使用模型进行数据操作的两种方法。
- 使用原始 sql 进行数据操作:
def upgrade():
op.execute(
"update user_account set email = concat(username, '@example.com') where email is null;"
)
def downgrade():
op.execute(
"update user_account set email = null where email like '%@example.com';"
)
- 直接在迁移中定义表: 如果想使用sqlalchemy进行数据操作,可以直接在迁移中手动定义表。这确保了迁移执行时的静态模式,并且不会依赖于模型中的更改。
from sqlalchemy import table, column, string
def upgrade():
# define the user_account table to work with data
user_account = table(
'user_account',
column('id'),
column('username', string),
column('email', string)
)
# get a connection to the database
conn = op.get_bind()
# select all users without an email
users = conn.execute(
user_account.select().where(user_account.c.email == none)
)
# update email for each user
for user in users:
conn.execute(
user_account.update().where(
user_account.c.id == user.id
).values(
email=f"{@example.com">user.username}@example.com"
)
)
def downgrade():
user_account = table(
'user_account',
column('id'),
column('email', string)
)
conn = op.get_bind()
# remove email for users added in the upgrade
conn.execute(
user_account.update().where(
user_account.c.email.like('%@example.com')
).values(email=none)
)
5. 迁移测试的阶梯测试
阶梯测试涉及逐步测试升级/降级迁移,以确保整个迁移链正常工作。这确保每次迁移都可以成功地从头开始创建新数据库并降级而不会出现问题。将此测试添加到 ci 对于团队来说非常宝贵,可以节省时间并减少挫败感。

将测试集成到您的项目中可以轻松快速地完成。您可以在此存储库中找到代码示例。它还包括其他可能有帮助的有价值的迁移测试。
6. 迁移服务
用于执行迁移的单独服务。这只是执行迁移的一种方法。当在本地或类似开发的环境中开发时,这种方法非常适合。我想提醒您有关条件 dependent_on 功能,该功能与此处相关。我们使用 alembic 获取应用程序映像并在单独的容器中运行它。我们添加对数据库的依赖关系,条件是仅当数据库准备好处理请求(service_healthy)时才开始迁移。此外,可以为应用程序添加条件依赖项(service_completed_successively),确保它仅在迁移成功完成后启动。
db:
image: postgres:15
...
healthcheck:
test: ["cmd-shell", "pg_isready -u ${postgres_user} -d ${postgres_db}"]
interval: 10s
start_period: 10s
app_migrations:
image: <app-image>
command: [
"python",
"-m",
"alembic",
"-c",
"<path>/alembic.ini",
"upgrade",
"head"
]
depends_on:
db:
condition: service_healthy
app:
...
depends_on:
app_migrations:
condition: service_completed_successfully
depends_on 条件确保迁移仅在数据库完全准备好后运行,并且应用程序在迁移完成后启动。
7. 模型的 mixins
虽然这可能是显而易见的一点,但重要的是不要忽视它。使用 mixins 是避免代码重复的便捷方法。 mixin 是包含常用字段和方法的类,可以将其集成到需要的任何模型中。例如,我们经常需要created_at和updated_at字段来跟踪记录的创建和更新时间。使用基于 uuid 的 id 来标准化主键也很有用。所有这些都可以封装在 mixin 中。
import uuid
from sqlalchemy import column, datetime, func
from sqlalchemy.dialects.postgresql import uuid
class timestampmixin:
created_at = column(
datetime,
server_default=func.now(),
nullable=false,
comment="record creation time"
)
updated_at = column(
datetime,
onupdate=func.now(),
nullable=true,
comment="unique record identifier"
)
class uuidprimarykeymixin:
id = column(
uuid(as_uuid=true),
primary_key=true,
default=uuid.uuid4,
comment="unique record identifier"
)
通过添加这些 mixins,我们可以在需要的任何模型中包含 uuid id 和时间戳:
class User(UUIDPrimaryKeyMixin, TimestampMixin, BaseModel):
__tablename__ = 'user'
# Other columns...
结论
处理迁移可能具有挑战性,但遵循这些简单的做法有助于保持项目井然有序且易于管理。命名约定、日期排序、注释和测试使我免于混乱并有助于防止错误。我希望这篇文章对您有所帮助——请随时在评论中分享您自己的迁移技巧!
到这里,我们也就讲完了《Alembic 和 SQLAlchemy 的最佳实践》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!
-
- 文章 · python教程 | 6小时前 |
- Pandas列扩展与行值移动方法
- 422浏览 收藏
-
- 文章 · python教程 | 6小时前 |
- FlaskSQLAlchemy更新用户积分教程详解
- 345浏览 收藏
-
- 文章 · python教程 | 6小时前 |
- Pandas行标准差计算方法详解
- 253浏览 收藏
-
- 文章 · python教程 | 7小时前 |
- Python调用srun性能分析与优化
- 263浏览 收藏
-
- 文章 · python教程 | 7小时前 |
- Python指定文件路径的方法及技巧
- 362浏览 收藏
-
- 文章 · python教程 | 7小时前 |
- Pandas统计连续相同值并新增列技巧
- 297浏览 收藏
-
- 文章 · python教程 | 8小时前 |
- DjangoQ对象使用技巧与优化方法
- 245浏览 收藏
-
- 文章 · python教程 | 8小时前 |
- Dagster数据流转与参数配置方法
- 211浏览 收藏
-
- 文章 · python教程 | 8小时前 |
- OpenCV调整亮度技巧与方法
- 204浏览 收藏
-
- 文章 · python教程 | 8小时前 |
- Python轻松生成九九乘法表并导出Excel
- 147浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3212次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3425次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3455次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4564次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3832次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

相位记录
