模型 unique_together 约束 + 无 = 失败?
Posted
技术标签:
【中文标题】模型 unique_together 约束 + 无 = 失败?【英文标题】:Models unique_together constraint + None = fail? 【发布时间】:2010-11-03 15:29:15 【问题描述】:2 个问题:
当 parent=None 且名称相同时,如何阻止创建重复项? 我可以从表单中调用模型方法吗?请参阅下面的完整详细信息:
models.py
class MyTest(models.Model):
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=255, blank=True, unique=True)
owner = models.ForeignKey(User, null=True)
class Meta:
unique_together = ("parent", "name")
def save(self, *args, **kwargs):
self.slug = self.make_slug()
super(MyTest, self).save(*args, **kwargs)
def make_slug(self):
# some stuff here
return generated_slug
注意:slug = 也是独一无二的!
forms.py
class MyTestForm(forms.ModelForm):
class Meta:
model = MyTest
exclude = ('slug',)
def clean_name(self):
name = self.cleaned_data.get("name")
parent = self.cleaned_data.get("parent")
if parent is None:
# this doesn't work when MODIFYING existing elements!
if len(MyTest.objects.filter(name = name, parent = None)) > 0:
raise forms.ValidationError("name not unique")
return name
详情
unique_together
约束与parent != None
时的形式完美配合。但是,当 parent == None
(null) 时,它允许创建重复项。
为了避免这种情况,我尝试使用表单并定义 clean_name 来尝试检查重复项。这在创建新对象时有效,但在修改现有对象时无效。
有人提到我应该在 ModelForm 的 .save 上使用 commit=False,但我不知道如何做/实现这个。我还考虑过使用 ModelForm 的 has_changed 来检测模型的更改并允许它们,但是 has_changed 在新创建的带有表单的对象上也返回 true。帮忙!
另外,(有点完全不同的问题)我可以从表单访问 make_slug() 模型方法吗?我相信目前我的exclude = ('slug',)
行也忽略了 slug 字段上的“唯一”约束,而在模型保存字段中,我正在生成 slug。我想知道是否可以改为在 forms.py 中执行此操作?
【问题讨论】:
请参阅***.com/questions/3488264/… 了解处理此问题的最新方法。需要 Django 1.2。 使用 Django2.2,您可以使用带有条件参数的 UniqueConstraints 来创建部分索引:docs.djangoproject.com/en/2.2/ref/models/constraints/#condition 【参考方案1】:无论是创建还是更新,您都可以有不同的表单。
在实例化表单时使用 instance kwarg。
if slug:
instance = MyTest.object.get( slug=slug )
form = MyUpdateTestForm( instance=instance )
else:
form = MyTestForm()
对于第二部分,我认为您可以在其中引入 commit=False,例如:
if form.is_valid():
inst = form.save( commit=False )
inst.slug = inst.make_slug()
inst.save()
【讨论】:
【参考方案2】:我不确定这是否能解决您的问题,但我建议在最新的 Django 主干代码上测试您的代码。得到它:
svn co http://code.djangoproject.com/svn/django/trunk/
自 1.02 版本以来,已经对 unique_together 进行了多项修复,例如参见 ticket 9493。
【讨论】:
【参考方案3】:唯一的一起应该是元组的元组
unique_together = (("parent", "name"),)
【讨论】:
以上是关于模型 unique_together 约束 + 无 = 失败?的主要内容,如果未能解决你的问题,请参考以下文章
约束 unique_together 可能与 django 类中的唯一字段冲突
为啥我的 Django ModelForm 不会引发 unique_together 约束的验证错误?
为啥 Django 不将我的 unique_together 约束强制为 form.ValidationError 而不是抛出异常?
如何在 MySQL 中有一个涉及 ForeignKey 字段的 unique_together 约束?