升级Wagtail1.9到2.0与Django1.10到2.0时遇is_relation属性错误
这个错误AttributeError: 'NoneType' object has no attribute 'is_relation'本质是Django在处理迁移时,找不到某个操作里引用的旧字段,返回None后尝试调用is_relation属性导致的。结合你跨版本升级的场景,我给你分步解决方案:
一、先修正升级路径(核心问题根源)
你直接跨大版本升级Django和Wagtail风险极高——Wagtail 2.0要求Django 1.11+,而你从Django 1.10跳升到2.0,跳过了关键的中间兼容版本,很容易出现迁移逻辑断裂。正确的升级步骤应该是:
- 第一步:把Django从1.10.6升级到1.11.x(建议用1.11系列的最新稳定版),运行
python manage.py migrate确保项目能正常启动和迁移。 - 第二步:把Wagtail从1.9升级到1.13.x(这是支持Django 1.11的最后一个Wagtail 1.x版本),再次运行迁移验证。
- 第三步:最后升级Django到2.0,同时升级Wagtail到2.0,执行迁移。
这种渐进式升级能避开很多跨版本的兼容性坑。
二、定位并修复有问题的迁移文件
如果渐进式升级后还是出现错误,或者你想直接排查当前问题,可以按以下步骤操作:
1. 找出出错的具体迁移
从错误栈可以看到,问题出在django/db/migrations/operations/fields.py的state_forwards方法里。你可以临时添加调试代码来定位具体的迁移:
打开虚拟环境里的这个文件(路径是/home/razia/.virtualenvs/web-dj2/lib/python3.6/site-packages/django/db/migrations/operations/fields.py),在报错的delay = not old_field.is_relation这一行之前添加:
# 临时调试代码 print(f"=== Debug Info ===") print(f"App: {app_label}") print(f"Model: {self.model_name}") print(f"Field being modified: {self.name}") print(f"Existing fields in state: {list(state.models[app_label, self.model_name].fields.keys())}")
然后重新运行python manage.py migrate,控制台会打印出哪个app、哪个模型的哪个字段操作出了问题。
2. 修复迁移文件
找到对应的迁移文件后(比如core/migrations/00XX_xxxx.py),检查里面的AlterField或RemoveField操作:
- 如果是
AlterField操作:确认里面的model_name和name是否对应存在的字段,旧字段的定义是否正确。如果字段已经被移除,你可能需要调整迁移的顺序,或者修改迁移内容使其匹配当前的模型状态。 - 如果是
RemoveField操作:确认这个字段确实存在于之前的模型版本中,或者如果字段已经被提前移除,你可以删除这个多余的RemoveField操作(但要确保不会影响数据)。
三、关键注意事项
- 备份优先:在做任何修改前,一定要备份你的数据库和代码仓库,防止意外数据丢失。
- 不要跳过中间版本:跨版本升级很容易导致迁移逻辑不兼容,尤其是Wagtail和Django的版本绑定比较严格,一定要遵循官方的升级指南逐步升级。
内容的提问来源于stack exchange,提问作者Razia Khan




