Django测试出现no such column错误,请求排查解决
解决Django测试中
sqlite3.OperationalError: no such column: recommended_for_text错误 问题核心分析
你的问题根源在于迁移顺序与测试数据库初始化时机的冲突:
- 加载旧fixture的迁移(0015)先于添加新字段的迁移(0016)执行,生产环境迁移完成后表能正常包含新字段,但测试场景下,若存在提前访问模型的代码,会在迁移未完全完成时尝试访问不存在的字段;
- 仅继承
TestCase的测试类报错、空测试正常,说明测试类中存在触发模型查询的代码,且该代码执行时机早于测试数据库的迁移完成时间。
分步解决方案
1. 强制重建测试数据库
测试数据库可能复用了未应用最新迁移的旧实例,强制重建可排除缓存问题:
python manage.py test --keepdb=False
2. 验证迁移文件正确性
- 打开0016号迁移文件,确认
AddField操作参数无误:- 目标模型、表名与实际一致;
- 字段名
recommended_for_text拼写正确; - 字段定义包含
null=True(符合可空设置);
- 确认0016迁移的
dependencies列表包含0015,保证迁移顺序正确执行。
3. 排查测试类中的提前查询代码
检查测试类是否在类级别(而非setUp或测试方法内部)定义了模型查询/实例化代码,这类代码会在测试数据库初始化前执行:
# 错误示例 class PlanTest(TestCase): # 此查询会在迁移完成前触发 test_plans = Plan.objects.all() def test_something(self): ...
将此类代码移至setUp方法或测试方法内部:
# 正确示例 class PlanTest(TestCase): def setUp(self): self.test_plans = Plan.objects.all() def test_something(self): ...
4. 检查模型信号的执行时机
若项目使用Django信号(如pre_migrate),确认信号处理函数未在迁移完成前访问recommended_for_text字段。可调整为post_migrate触发,或在函数内增加字段存在性判断后再执行逻辑。
5. 调整迁移顺序(可选)
如果加载fixture的操作不依赖旧数据结构,可重新整理迁移顺序:
- 暂时删除0015、0016迁移文件;
- 先执行添加字段操作,生成新的迁移文件;
- 再创建加载fixture的迁移文件,确保其依赖添加字段的迁移,保证加载fixture时表已包含新字段。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

