Django unique_together与可为空的ForeignKey [英] Django unique_together with nullable ForeignKey
问题描述
我在使用Sqlite的开发机中使用Django 1.8.4,并且具有以下模型:
I'm using Django 1.8.4 in my dev machine using Sqlite and I have these models:
class ModelA(Model):
field_a = CharField(verbose_name='a', max_length=20)
field_b = CharField(verbose_name='b', max_length=20)
class Meta:
unique_together = ('field_a', 'field_b',)
class ModelB(Model):
field_c = CharField(verbose_name='c', max_length=20)
field_d = ForeignKey(ModelA, verbose_name='d', null=True, blank=True)
class Meta:
unique_together = ('field_c', 'field_d',)
我已经进行了适当的迁移,并在Django Admin中注册了它们.因此,使用管理员我已经完成了以下测试:
I've run proper migration and registered them in the Django Admin. So, using the Admin I've done this tests:
- 我能够创建ModelA记录,而Django禁止我创建重复的记录-符合预期!
- 当field_b不为空时,我无法创建相同的ModelB记录
- 但是,当使用field_d为空时,我能够创建相同的ModelB记录
我的问题是:如何为可为空的ForeignKey应用unique_together?
My question is: How do I apply unique_together for nullable ForeignKey?
我找到的关于该问题的最新答案有5年了...我确实认为Django已经发展并且问题可能并不相同.
The most recent answer I found for this problem has 5 year... I do think Django have evolved and the issue may not be the same.
推荐答案
更新:我的答案的上一版功能正常,但设计不好,该版本考虑了一些评论和其他答案
UPDATE: previous version of my answer was functional but had bad design, this one takes in account some of the comments and other answers.
在SQL中,NULL不等于NULL.这意味着,如果您有两个field_d == None and field_c == "somestring"
不相等的对象,则可以创建两个对象.
In SQL NULL does not equal NULL. This means if you have two objects where field_d == None and field_c == "somestring"
they are not equal, so you can create both.
您可以覆盖Model.clean
来添加支票:
You can override Model.clean
to add your check:
class ModelB(Model):
#...
def validate_unique(self, exclude=None):
if ModelB.objects.exclude(id=self.id).filter(field_c=self.field_c, \
field_d__isnull=True).exists():
raise ValidationError("Duplicate ModelB")
super(ModelB, self).validate_unique(exclude)
如果在表格之外使用,则必须调用full_clean
或validate_unique
.
If used outside of forms you have to call full_clean
or validate_unique
.
尽管如此,还是要小心处理比赛状况.
Take care to handle the race condition though.
这篇关于Django unique_together与可为空的ForeignKey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!