升级至Django Oscar 1.6时出现LookupError:promotions无KeywordPromotion模型
你遇到的这个问题确实和Oscar 1.6引入的动态加载变更直接相关。在1.6版本之前,Oscar使用直接导入的方式加载模型,但新版本改为动态加载(通过get_model())来提升扩展性,这意味着自定义扩展应用的配置要求更严格了。结合你的情况,我整理了几个核心原因和对应的解决步骤:
一、核心原因分析
你的自定义promotions应用没有正确接入Oscar的应用覆盖机制,导致Oscar的动态加载系统无法找到你扩展后的模型。当你移除自定义应用后,Oscar会默认使用原生的promotions应用,所以能正常运行——这说明原生应用本身没问题,问题出在你的扩展配置上。
二、具体解决步骤
1. 检查自定义Promotions应用的配置文件
Oscar 1.6要求扩展应用必须正确配置apps.py,确保继承自核心应用的配置类,并设置正确的name属性:
# your_project/promotions/apps.py from oscar.apps.promotions.apps import PromotionsConfig as CorePromotionsConfig class PromotionsConfig(CorePromotionsConfig): # 这里必须是自定义应用的完整Python路径 name = 'your_project.promotions' verbose_name = 'Custom Promotions'
2. 确保自定义应用在INSTALLED_APPS中优先加载
在settings.py中,使用Oscar的get_core_apps()方法来包含你的自定义应用,这样Oscar会自动优先使用你的扩展应用,而不是原生的oscar.apps.promotions:
# settings.py from oscar import get_core_apps INSTALLED_APPS = [ # 你的其他Django应用,比如django.contrib.admin等 'django.contrib.admin', 'django.contrib.auth', # ... ] + get_core_apps([ 'your_project.promotions', # 其他你扩展的Oscar应用 ])
3. 替换直接模型导入为动态加载
Oscar 1.6不再推荐直接导入模型(比如from oscar.apps.promotions.models import KeywordPromotion),而是要求使用动态加载方式。把代码中所有直接导入的地方替换为:
# 使用Django原生的apps.get_model from django.apps import apps KeywordPromotion = apps.get_model('promotions', 'KeywordPromotion') # 或者使用Oscar提供的加载工具(更推荐,适配Oscar的扩展机制) from oscar.core.loading import get_model KeywordPromotion = get_model('promotions', 'KeywordPromotion')
4. 确保自定义模型正确继承核心模型
如果你的KeywordPromotion模型做了少量定制,要确保它正确继承自Oscar的核心模型:
# your_project/promotions/models.py from oscar.apps.promotions.models import KeywordPromotion as CoreKeywordPromotion class KeywordPromotion(CoreKeywordPromotion): # 你的定制代码,比如新增字段、重写方法等 # example: # custom_field = models.CharField(max_length=100, blank=True) pass
5. 更新数据库迁移
最后,重新生成并应用迁移,确保自定义模型的结构被正确同步到数据库:
python manage.py makemigrations promotions python manage.py migrate
三、验证解决效果
完成以上步骤后,重新启动Django服务,应该就不会再出现LookupError: App 'promotions' doesn't have a 'KeywordPromotion' model的错误了。如果还有问题,可以检查:
- 自定义应用的目录结构是否正确(比如
models.py是否存在、__init__.py是否为空或正确导入模型) - 是否有其他代码仍在直接导入原生Oscar的promotions模型
内容的提问来源于stack exchange,提问作者Steve Bradshaw




