0

我有一个模型 ( A),它有 2 个外键:bc.

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 插入一次。这很棒:)

但是,剩余的行对我来说是重复的条目,我想限制这一点。

更新

我找到了一些可以完成工作的东西,但它看起来真的很hacky..有什么想法吗?

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")
4

3 回答 3

1

也许那里有更好的解决方案,但您可以执行以下操作:

  1. 创建一个新属性d并找到一种通用方法来组合b_idc_id(例如str(b_id) + "*" + str(c_id),在模型创建时自动执行此操作(信号机制可能会派上用场,在这里)
  2. 用作dprimary_key

这更像是一种解决方法,而不是一种解决方案,但它应该可以解决问题。

再想一想:在创建/更新实例时检查是否存在具有“Null”/“Null”的现有实例是否是一种选择?这不会解决您在数据库级别的问题,但逻辑会按预期工作。

于 2013-10-29T10:53:22.657 回答
1

这不是 Django 的问题,而是 SQL 规范本身的问题 - NULL 不是一个值,因此在唯一性约束检查中不能考虑它。

您可以在您的数据库中拥有一个“伪空”B 记录和一个“伪空”C 记录,并将它们设为默认值(当然不允许 NULL),或者像 OBu 建议的那样拥有一个非规范化字段。

于 2013-10-29T11:16:36.273 回答
-1

您可以对b_id列使用唯一约束。它不会允许重复的条目。即使对于 a_id 列,也可以使用主键。主键是指唯一键和非空约束的组合。

于 2013-10-29T10:16:08.570 回答