使用django-modeltranslation注册继承MPTTModel的模型时出错
解决Django2.0 + modeltranslation + mptt 继承模型翻译注册错误
我之前也碰到过几乎一模一样的问题,结合你使用的这些版本(Django 2.0.1、django-modeltranslation 0.12.2、django-mptt 0.9.0),大概率是modeltranslation和mptt在模型元类处理、字段注册顺序上的兼容性冲突,尤其是继承MPTTModel的模型在注册翻译时容易踩坑。下面是我亲测有效的解决方案:
1. 检查模型定义与翻译注册的正确性
首先确保你的Category模型定义和翻译注册逻辑没有问题,核心是不要翻译mptt的内部管理字段(比如lft、rght、tree_id、level),只翻译业务字段:
from django.db import models from mptt.models import MPTTModel, TreeForeignKey from modeltranslation.translator import register, TranslationOptions class Category(MPTTModel): # 业务字段,需要翻译 name = models.CharField(max_length=255) # MPTT的外键字段,不需要翻译 parent = TreeForeignKey( 'self', on_delete=models.CASCADE, null=True, blank=True, related_name='children' ) class MPTTMeta: order_insertion_by = ['name'] # 只注册需要翻译的字段,避开mptt内部字段 @register(Category) class CategoryTranslationOptions(TranslationOptions): fields = ('name',)
2. 调整INSTALLED_APPS的顺序
第三方app的加载顺序会影响元类的处理逻辑,必须把modeltranslation放在mptt和你的业务应用之前,这样它才能正确处理模型的翻译扩展:
# settings.py INSTALLED_APPS = [ # Django内置app 'django.contrib.admin', 'django.contrib.auth', ... # 先加载modeltranslation 'modeltranslation', # 再加载mptt 'mptt', # 最后加载你的业务应用 'listing', ... ]
3. 重新生成并执行迁移
modeltranslation会自动为翻译字段生成带语言后缀的数据库字段(比如name_en、name_fr),如果之前的迁移没有正确生成这些字段,就会导致查询出错:
# 若业务应用未上线可安全重置迁移,否则跳过删除步骤 rm -rf listing/migrations/ # 重新生成迁移 python manage.py makemigrations # 执行迁移 python manage.py migrate
4. 手动指定MPTT管理器(可选)
如果上面的步骤还是没解决问题,可以尝试手动为模型指定MPTTManager,避免modeltranslation覆盖默认的管理器:
from mptt.managers import MPTTManager class Category(MPTTModel): # ... 字段定义 ... # 手动指定管理器 objects = MPTTManager()
5. 检查modeltranslation的语言配置
确保在settings.py中正确配置了翻译语言,这会影响modeltranslation的字段生成逻辑:
# settings.py from django.utils.translation import gettext_lazy as _ # 支持的语言 LANGUAGES = [ ('en', _('English')), ('fr', _('French')), # 根据你的需求添加其他语言 ] # modeltranslation相关配置 MODELTRANSLATION_LANGUAGES = ('en', 'fr') MODELTRANSLATION_DEFAULT_LANGUAGE = 'en' MODELTRANSLATION_TRANSLATION_FILES = ( 'listing.translations', )
按照这个流程走下来,应该就能解决你在CategoryListView中调用Category.objects.root_nodes()时出现的错误了。
内容的提问来源于stack exchange,提问作者Peter Sobhi
相关产品推荐
相关产品推荐

