数据迁移报错:AttributeError - ContentType对象无model_class属性
解决Django迁移中调用
ContentType.model_class()出现的AttributeError 这个问题我之前帮不少开发者排查过,核心原因是Django迁移的运行上下文和普通业务代码完全不同:迁移过程中使用的是历史版本的模型快照(通过apps参数提供),而直接调用ContentType.model_class()会尝试加载当前项目的最新模型,两者状态不匹配,就会抛出AttributeError。
解决方案:改用apps.get_model()获取模型
迁移函数里的apps参数是专门用来获取当前迁移上下文对应模型的入口,用它替代model_class()就能解决问题。修改后的代码如下:
def set_target_user(apps, schema_editor): LogEntry = apps.get_model('auditlog', 'LogEntry') ContentType = apps.get_model('contenttypes', 'ContentType') for entry in LogEntry.objects.filter(target_user=None): # 通过content_type的app_label和model名称,从apps中获取对应模型 model = apps.get_model(entry.content_type.app_label, entry.content_type.model) # 这里写你后续的业务逻辑,比如根据model获取实例并设置target_user
额外的健壮性优化
如果你的项目中有过模型删除、重命名的情况,最好加上异常处理,避免迁移因为找不到模型而中断:
def set_target_user(apps, schema_editor): LogEntry = apps.get_model('auditlog', 'LogEntry') ContentType = apps.get_model('contenttypes', 'ContentType') for entry in LogEntry.objects.filter(target_user=None): try: model = apps.get_model(entry.content_type.app_label, entry.content_type.model) # 你的业务逻辑 except LookupError: # 跳过不存在的模型对应的LogEntry,或者做其他处理 continue
为什么普通模块里代码能正常运行?
在非迁移模块中,ContentType.model_class()会直接加载当前项目的最新模型定义,此时模型的状态和ContentType记录是匹配的,所以不会出错。但迁移场景下必须依赖apps参数提供的历史模型上下文,否则就会出现兼容性问题。
内容的提问来源于stack exchange,提问作者Dmitry Sazhnev
相关产品推荐
相关产品推荐

