簡體   English   中英

Django:外鍵是可選的,但唯一?

[英]Django: Foreign key optional but unique?

我有一個具有2個外鍵的模型( A ): bc

bc應該一起唯一, 包括NULL

因此bc只應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")

也許有更好的解決方案,但是您可以執行以下操作:

  1. 創建一個新的屬性d並找到一種組合b_idc_id的通用方法(例如str(b_id) + "*" + str(c_id) ,並在模型創建時自動執行(信號機制可能會派上用場)
  2. 使用d作為primary_key

這是更多的解決方案,而不是解決方案,但是應該可以解決問題。

再想一想:是否可以選擇在創建/更新實例時檢查現有實例是否帶有“ Null” /“ Null”? 這不會在數據庫級別解決您的問題,但是邏輯將按預期工作。

這不是Django的問題,而是SQL規范本身的問題-NULL不是值,因此唯一性約束檢查不得將其考慮在內。

您可以在數據庫中擁有一個“偽空” B記錄和一個“偽空” C記錄,並將它們設置為默認值(當然不允許NULL),或者可以像OBu建議的那樣使用非規范化字段。

您可以對b_id列使用“ 唯一性”約束。 它不允許重復的條目 即使對於a_id列,也可以使用主鍵 主鍵是指唯一鍵和非空約束的組合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM