【问题标题】:unique_together is not working with self referencing foreign key? [duplicate]unique_together 不使用自引用外键? [复制]
【发布时间】:2020-11-16 05:41:59
【问题描述】:
class Category(models.Model):
    name = models.CharField(max_length=200)
    parent = models.ForeignKey("self",
                               blank=True,
                               null=True,
                               related_name='children',
                               on_delete=models.CASCADE)

    class Meta:
        unique_together = [
            ('parent', 'name'),
        ]

在这个模型中,我可以创建多个对象

Category.objects.create(name="cat1", parent=None) # 
Category.objects.create(name="cat1", parent=None) 
# unique_together constraint should not 
# allow this second object's reaction, but it is; 
# behavior is the same even when the parent is not None.

我使用的Django版本是3.0.8 Postgres 12.3 psycopg2-二进制 2.8.5

更新:

Category.objects.create(name="cat1", parent=obj) # 
Category.objects.create(name="cat1", parent=obj) 

第二个对象或记录正在被创建,即使 parent 不是 None。

In [2]: Category2.objects.create(name="cat1")                            
Out[2]: <Category2: cat1>

In [3]: Category2.objects.create(name="cat1")                            
Out[3]: <Category2: cat1>

In [4]: par1 = Category2.objects.create(name="cat1")                     

In [6]: par1 = Category2.objects.create(name="cat2", parent=par1)        

In [7]: par2 = Category2.objects.create(name="cat2", parent=par1)  

这个问题不是重复的,它与问题中解释的可空外键无关。

【问题讨论】:

  • 在我的情况下,即使使用非空字段值,我也能够创建记录
  • 您能否举例说明使用非空值时发生的错误?
  • 你跑makemigrations和migrate了吗?
  • javed:数据库不认为两个NULLs 是相同的。所以NULL 不会“违反”唯一性约束。
  • @IainShelvington:抱歉,自动补全:S

标签: django django-models


【解决方案1】:

数据库在检查 uniqness 时会忽略 NULL,因此这意味着两个 NULLs 不被视为分支 uniqness。

您可以利用约束框架有条件地检查唯一性:

from django.db.models import Q, UniqueConstraint

class Category(models.Model):
    name = models.CharField(max_length=200)
    parent = models.ForeignKey(
        'self',
        blank=True,
        null=True,
        related_name='children',
        on_delete=models.CASCADE
    )

    class Meta:
        constraints = [
            UniqueConstraint(
                fields=['name', 'parent'], name='name_unique'
            ),
            UniqueConstraint(
                fields=['name'], condition=Q(parent=None), name='name_unique2'
            )
        ]

这里如果parent 是NULL,我们检查name 的唯一性。但是,某些数据库可能不会强制执行此类检查。

显然,在 Microsoft 的 SQL Server 上,情况并非如此,正如@Melvyn 所说。在这种情况下,这将是通缉行为。但在我看来,这通常是不受欢迎的行为。 NULL 经常用于此目的。

【讨论】:

  • NULL 不是值(但没有值)的规则的一个例外是 Microsoft SQL Server。使处理可空的一对一字段成为一项挑战。
猜你喜欢
  • 2016-08-28
  • 1970-01-01
  • 2012-05-06
  • 1970-01-01
  • 2015-02-26
  • 1970-01-01
  • 2021-07-31
  • 2013-02-23
相关资源
最近更新 更多