如何解决Django:对于唯一性约束,如何将 null 视为等于所有内容?
在标题中我的意思是等于任何值,而不仅仅是其他空值。
假设我们有一个家庭,有家庭成员(人)和电子设备。有些电子设备是个人的,属于一个人,但有些不属于任何一个家庭成员,例如书房中的一台普通电脑。 然后我们可能会像这样对电子设备进行建模:
class ElectronicDevice(models.Model):
name = models.CharField(null=False,max_length=64)
owner = models.ForeignKey(HouseMember,null=True,on_delete=models.CASCADE)
现在假设我们希望设备名称从家庭成员的角度来看是唯一的。家庭成员不应有两个同名设备可供他们使用。所以名称和所有者应该是唯一的,但也不应该有两个设备,一个私有的和一个公共的(所有者为空)具有相同的名称。
因此是正常的 UniqueConstraint
:
class Meta:
constraints = [
models.UniqueConstraint(fields=['name','owner'],name='uniqe_device_name'),]
不会,因为如果其中一个所有者为空,它仍然允许两个设备具有相同的名称。 仅约束名称字段:
class Meta:
constraints = [
models.UniqueConstraint(fields=['name',],]
也不会这样做,因为这不允许两个家庭成员将他们的私人设备命名为相同的名称,尽管我们确实希望允许这样做。
我目前的尝试是限制名称和所有者的唯一性,然后使用 CheckConstraint
不允许名称,如果已经有一个具有该名称的通用设备(所有者为空):
class Meta:
constraints = [
models.UniqueConstraint(fields=['name',models.CheckConstraint(check=???,name='no_common_device_with_same_name')
]
这是最好的方法还是有更好的解决方案?
如果这是最佳解决方案:如何为此编写 CheckConstraint
?
解决方法
也许你可以这样尝试:
constraints = [
models.UniqueConstraint(fields=['name','owner'],condition = Q(owner__isnull=False),name='uniqe_device_name'),models.UniqueConstraint(fields=['name'],condition = Q(owner__isnull=True),name='uniqe_device_name_without_owner')
]
可以在documentation中找到更多信息。
更新
如果您需要无法通过约束处理的自定义条件,那么最好覆盖保存方法。例如:
class ElectronicDevice(models.Model):
...
def save(self,*args,**kwargs):
if some conditions:
raise ValidationError()
super().save(*args,**kwargs)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。