python - Django / MySQL唯一约束如何将NULL视为平等
问题描述
我有一个具有递归字段的 Django 模型。简化版本如下。这个想法大致是在sql中有一个树形数据结构。我遇到的问题是,显然,Django 不将 NULLs 视为 equal。现在的问题是,由于每棵树的根都必须有一个“空指针”,我可以有两棵相同的树,但由于 NULL 值,Django 会将它们视为不同的。如何实现下面的 UniqueConstraint,以便两个具有 NULL 链接值和相等节点值的“链接”对象将被视为相同,并且无法通过 UniqueConstraint 测试?谢谢你。
class Link(models.Model):
node = models.ForeignKey(Node, on_delete=models.CASCADE)
link = models.ForeignKey('self', on_delete = models.CASCADE, null=True)
class Meta:
constraints = [
models.UniqueConstraint(['node', 'link'], name='pipe_unique')
]
编辑 当然,理想情况下,约束将由 db 强制执行。但即使我可以通过在某处挂钩或使用自定义约束在应用程序逻辑中强制执行它,那也足够了。
解决方案
您可以使用自定义约束来执行此操作
UniqueConstraint(fields=['node'], condition=Q(link__isnull=True), name='unique_root_node')
编辑:
如果您希望手动添加检查,您可以在save
方法Link
和方法中执行此操作clean
,以便在您保存实例之前它可以在任何模型表单中运行
def clean(self):
if self.node_id and not self.link_id:
if self.__class__.objects.exclude(pk=self.pk).filter(node=self.node, link__isnull=True).exists():
raise ValidationError(f'A root node already exists for {self.node}')
排除pk=self.pk
在更新对象时避免与自身发生冲突
def save(self, *args, **kwargs):
self.clean()
super().save(*args, **kwargs)
推荐阅读
- javascript - JQuery 添加/删除类无法正常工作
- java - 如何阻止 spring-boot Embedded-undertow 添加斜杠
- arrays - Ruby - 按第一行对多维数组进行排序
- angularjs - 如何解决问题 - 在控制器上未找到与从 AngularJS 向 ASP.NET WebAPI 发送 JSON 对象时的名称匹配的操作
- apache - apache 反向代理到 mTLs 服务
- database - JPG 图像扩展名未插入到 wp 的自定义表中
- java - Microsoft SQL Server:“登录失败。登录来自不受信任的域,不能用于 Windows 身份验证。”
- java - 如何从控制台启动我的应用程序作为服务器?
- node.js - Mongoosastic 不保存索引
- r - 从 R 闪亮的打开对话框中停止 dropdownButton(闪亮的小部件)