运行Django测试时出现Duplicate column name 'table_id'错误求助
解决Django测试中MySQL重复列名错误的方案
看起来你在运行Django测试时遇到了MySQL的重复列名错误,而且--fake-initial没能解决问题。我来帮你一步步排查和解决:
首先修复测试代码中的明显问题
你的setUp方法里有个容易被忽略的错误:给Table的restaurant外键字段赋值时用了filter(),它返回的是QuerySet集合,但ForeignKey需要单个模型实例。这个错误虽然不是直接导致重复列的原因,但会引发其他ORM错误,先修正它:
修改Test.py中的Table创建代码:
# 原来的写法(错误) restaurant=Restaurant.objects.filter(name="Test Restaurant"), # 改成下面两种之一(正确) restaurant=Restaurant.objects.get(name="Test Restaurant"), # 或者用first()更安全,避免get()找不到数据抛出异常 restaurant=Restaurant.objects.filter(name="Test Restaurant").first(),
排查并解决重复列名的核心问题
Duplicate column name 'table_id'错误通常是迁移文件与数据库状态不匹配导致的,Django测试时会自动创建测试数据库并执行所有迁移,迁移文件中的重复操作会触发这个错误。
方案1:重置迁移文件(开发/测试环境适用)
如果你的项目还在开发阶段,没有生产数据,可以彻底重置迁移:
- 清除reservations应用的迁移记录:
python3 manage.py migrate reservations zero
- 删除reservations/migrations目录下除了
__init__.py之外的所有迁移文件:
rm reservations/migrations/0*.py
- 重新生成初始迁移:
python3 manage.py makemigrations reservations
- 执行迁移:
python3 manage.py migrate
- 重新运行测试:
python3 manage.py test
方案2:排查并修复有问题的迁移文件
如果不想重置所有迁移,可以手动检查迁移文件:
- 打开reservations/migrations目录下的所有文件,查找包含
AddField操作且字段名为table_id的代码段。比如是否有某个迁移重复添加了这个列(因为ForeignKey会自动生成table_id外键列,手动添加会导致重复)。 - 如果找到重复的迁移操作,可以删除该迁移文件,或者用
--fake标记该迁移已执行:
# 替换0002_xxxx为你找到的有问题的迁移文件名前缀 python3 manage.py migrate --fake reservations 0002_xxxx
方案3:手动清理测试数据库
有时候测试数据库的状态异常,直接删除重建更高效:
- 登录MySQL,删除测试数据库(默认名称是
test_<你的主数据库名>):
mysql -u 你的用户名 -p -e "DROP DATABASE test_你的数据库名;"
- 直接运行测试,Django会自动重新创建测试数据库并执行正确的迁移:
python3 manage.py test
额外注意事项
- 确保你的模型定义中没有手动添加
table_id字段:Reservation模型中的table = models.ForeignKey(...)会自动生成table_id外键列,手动添加会导致冲突。 - 如果你在Linux环境下,注意MySQL的表名是区分大小写的,Windows则不区分,确保模型和迁移中的表名一致。
内容的提问来源于stack exchange,提问作者Sander Lindberg




