[英]Django: Foreign key optional but unique?
我有一个具有2个外键的模型( A
): b
和c
。
b
和c
应该一起唯一, 包括NULL
因此b
和c
只应NULL一起ONCE
但是,我无法在Django中完成此操作。 这是我到目前为止的代码。 任何帮助表示赞赏!
-_-
class A(models.Model):
b = models.ForeignKey('B', blank = True, null = True)
c = models.ForeignKey('C', blank = True, null = True)
class Meta:
unique_together = (
('b', 'c')
)
此代码将在数据库中产生以下有害结果:
+----+------+------+
| id | b_id | c_id |
+----+------+------+
| 1 | 2 | 3 |
| 2 | 2 | 77 |
| 3 | 2 | NULL |
| 4 | 2 | NULL |
| 5 | NULL | NULL |
| 6 | NULL | NULL |
+----+------+------+
前2行只能由django插入一次。 太好了 :)
但是,剩余的行对我来说是重复的条目,我想对此进行限制。
UPDATE
我发现可以完成工作的东西,但看起来确实很hack ..有什么想法吗?
class A(models.Model):
def clean(self):
from django.core.exceptions import ValidationError
if not any([self.b, self.c]):
if Setting.objects.filter(b__isnull = True, c__isnull = True).exists():
raise ValidationError("Already exists")
elif self.b and not self.c:
if Setting.objects.filter(c__isnull = True, b = self.b).exists():
raise ValidationError("Already exists")
elif self.c and not self.user:
if Setting.objects.filter(c = self.c, b__isnull = True).exists():
raise ValidationError("Already exists")
也许有更好的解决方案,但是您可以执行以下操作:
d
并找到一种组合b_id
和c_id
的通用方法(例如str(b_id) + "*" + str(c_id)
,并在模型创建时自动执行(信号机制可能会派上用场) d
作为primary_key 这是更多的解决方案,而不是解决方案,但是应该可以解决问题。
再想一想:是否可以选择在创建/更新实例时检查现有实例是否带有“ Null” /“ Null”? 这不会在数据库级别解决您的问题,但是逻辑将按预期工作。
这不是Django的问题,而是SQL规范本身的问题-NULL不是值,因此唯一性约束检查不得将其考虑在内。
您可以在数据库中拥有一个“伪空” B记录和一个“伪空” C记录,并将它们设置为默认值(当然不允许NULL),或者可以像OBu建议的那样使用非规范化字段。
您可以对b_id列使用“ 唯一性”约束。 它不允许重复的条目 。 即使对于a_id列,也可以使用主键 。 主键是指唯一键和非空约束的组合。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.