如何在Django Parler中实现各语言内标题唯一?
解决django-parler多语言环境下标题按语言唯一的问题
问题背景
使用django-parler实现多语言模型时,尝试给波兰语添加与英文相同的标题“Sport”,无论从管理面板操作还是加载fixture都会报错,提示标题已存在。排查发现是因为TranslatedFields中的title字段设置了unique=True——这个约束是全局生效的,而非按语言维度限制。需要实现同语言内标题唯一,但不同语言允许使用相同标题的需求。
相关代码参考
- 初始错误模型代码:
translations = TranslatedFields( title=models.CharField(_('Title'), unique=True, max_length=40, null=False, blank=False) )
- django-parler配置:
PARLER_LANGUAGES = { None: ( {'code': 'en',}, # English {'code': 'pl',}, # Polish {'code': 'uk',}, # Ukrainian ), 'default': { 'fallbacks': ['en'], 'hide_untranslated': False, } }
- 当前模型(已移除全局unique约束):
class InterestsGroup(TranslatableModel): ''' Group for storing similar interests (that are related to same topic) ''' translations = TranslatedFields( title=models.CharField(_('Title'), unique=False, max_length=40, null=False, blank=False) ) class Meta: verbose_name = _('Interests Group') verbose_name_plural = _('Interests Groups') ordering = ['id']
解决方案
1. 确保移除全局唯一约束
先确认TranslatedFields里的title字段已经设置unique=False(或直接省略该参数,默认值为False),避免全局唯一的限制。
2. 添加按语言维度的联合唯一约束
django-parler自动生成的翻译表会包含language_code字段,我们需要给翻译表添加title和language_code的联合唯一约束,通过TranslationsMeta类来配置翻译表的元数据:
方式一:使用unique_together(兼容旧版Django)
from django.db import models from parler.models import TranslatableModel, TranslatedFields class InterestsGroup(TranslatableModel): ''' Group for storing similar interests (that are related to same topic) ''' translations = TranslatedFields( title=models.CharField(_('Title'), max_length=40, null=False, blank=False) ) class Meta: verbose_name = _('Interests Group') verbose_name_plural = _('Interests Groups') ordering = ['id'] class TranslationsMeta: # 配置翻译表的联合唯一约束:同一语言下标题唯一 unique_together = (('title', 'language_code'),)
方式二:使用UniqueConstraint(Django 2.2+推荐)
from django.db import models from parler.models import TranslatableModel, TranslatedFields class InterestsGroup(TranslatableModel): ''' Group for storing similar interests (that are related to same topic) ''' translations = TranslatedFields( title=models.CharField(_('Title'), max_length=40, null=False, blank=False) ) class Meta: verbose_name = _('Interests Group') verbose_name_plural = _('Interests Groups') ordering = ['id'] class TranslationsMeta: constraints = [ models.UniqueConstraint( fields=['title', 'language_code'], name='unique_title_per_language' ) ]
3. 应用数据库迁移
修改模型后,执行以下命令生成并应用迁移,让数据库层面的约束生效:
python manage.py makemigrations python manage.py migrate
这样配置后,同一语言(如英文)下不能有重复的title,但不同语言(如英文和波兰语)可以同时使用“Sport”作为标题,完全满足需求。
内容的提问来源于stack exchange,提问作者Yulian Rudenko
相关产品推荐
相关产品推荐

