Django迁移可在自定义命令读取但pytest测试中无数据如何解决
解决方法
根因分析
你运行测试时添加的--no-migrations是pytest-django提供的特性,该参数的核心逻辑就是主动禁用迁移加载流程,会把所有INSTALLED_APPS下的迁移模块临时替换为空占位符,因此MigrationLoader无法扫描到任何迁移文件,自然返回空的root nodes列表。
解决方案
方案1:直接移除--no-migrations参数(最简推荐)
MigrationLoader.build_graph()本身只会扫描本地迁移文件构建依赖关系,不会执行任何迁移操作,也不会读写数据库,完全符合你「无需执行migrations即可检测迁移错误」的需求,直接修改测试运行命令即可:
pytest
方案2:兼容其他测试需要--no-migrations的场景
如果你的其他测试确实依赖--no-migrations提升运行速度,可以给迁移校验测试做单独适配:
- 首先在
pytest.ini中添加自定义标记,区分迁移校验类测试:
[pytest] DJANGO_SETTINGS_MODULE = django_project.settings python_files = tests.py test_*.py markers = migration_check: 标记为迁移校验测试,强制加载迁移文件
- 给测试函数添加标记,临时关闭迁移禁用逻辑:
import pytest from django.db.migrations.loader import MigrationLoader from pytest_django.fixtures import _disable_migrations @pytest.mark.migration_check def test_multiple_leaf_nodes_in_migration_graph(settings): # 临时恢复迁移加载配置 if _disable_migrations: settings.MIGRATION_MODULES = {} migration_loader = MigrationLoader(None) migration_loader.build_graph() # 你的校验逻辑示例 assert not migration_loader.graph.conflicts, "存在迁移冲突" for root_node in migration_loader.graph.root_nodes(): app_name = root_node[0] print(app_name)
- 分开执行测试即可:
# 先跑迁移校验(不需要加--no-migrations) pytest -m migration_check # 再跑其他业务测试,保留--no-migrations提升速度 pytest -m "not migration_check" --no-migrations
扩展建议
你可以直接扩展该测试的校验逻辑,覆盖更多常见迁移问题,全程不需要执行迁移:
- 检测是否有未生成的迁移:对比模型状态与迁移快照的差异
- 检测迁移依赖循环
- 检测是否包含删除字段、删除表等高危数据操作
内容的提问来源于stack exchange,提问作者Cristiano Araujo
相关产品推荐
相关产品推荐

