DJANGO>;2.2-外键A、B或外键A、B、C一起唯一

DJANGO>;2.2-外键A、B或外键A、B、C一起唯一,django,python-3.x,postgresql,django-models,Django,Python 3.x,Postgresql,Django Models,在Django 2.2中,您可以一起摆脱unique\u而使用约束列表和UniqueConstraint类,该类非常方便,因为它具有条件参数 MyObject有三个外键,其中一个是可选的 class MyObject(ModelBase): parent=... # mandatory source=... # mandatory subsource=... # optional class Meta: constraints = [

在Django 2.2中,您可以一起摆脱
unique\u
而使用
约束
列表和
UniqueConstraint
类,该类非常方便,因为它具有
条件
参数

MyObject有三个外键,其中一个是可选的

class MyObject(ModelBase):
    parent=... # mandatory
    source=... # mandatory
    subsource=... # optional

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["parent", "source", "subsource"],    
                name="unique_subsource"
            ),
            models.UniqueConstraint(
                fields=["parent", "source"],
                condition=models.Q(subsource=None),
                name="unique_source",
            ),
        ]
假设我尝试依次创建以下对象和预期验证:

parent   source   subsource   valid?
1.       1.       1.          yes
1.       1.       2.          yes
1.       1.       -           yes
1.       1.       -           no
1.       1.       3.          yes
1.       2.       -           yes
...
所以我写了两个测试:

def test_unique1(self):
    """ unique parent/source/subsource """
    parent = ParentFactory()
    source = SourceFactory()
    subsource = SubsourceFactory()
    MyObjectFactory(parent=parent, source=source, subsource=subsource)
    myobj = MyObjectFactory.build(parent=parent, source=source, subsource=subsource)
    self.should_raise_validation_error(myobj)

def test_unique2(self):
    """ unique parent/source """
    parent = ParentFactory()
    source = SourceFactory()
    subsource = SubsourceFactory()
    MyObjectFactory(parent=parent, source=source)
    myobj = MyObjectFactory.build(parent=parent, source=source)
    self.should_raise_validation_error(myobj)
但后者不会引起任何验证错误:

.....F.
======================================================================
FAIL: test_unique2
unique parent/source/subsource
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/sebastiennicolaidis/dev/python/scientcap/macrovars/tests/models/test_dsflink.py", line 50, in test_unique2
    self.should_raise_validation_error(dsflink)
  File "/Users/sebastiennicolaidis/dev/python/scientcap/shared/tests/base_model_test.py", line 9, in should_raise_validation_error
    instance.full_clean()
AssertionError: ValidationError not raised

----------------------------------------------------------------------
Ran 7 tests in 0.141s
sqlmigrate的[UPDATE 2]输出:
我认为解决方案是创建约束和条件

class MyObject(ModelBase):
    parent=... # mandatory
    source=... # mandatory
    subsource=... # optional

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["parent", "source", "subsource"],    
                condition=models.Q(subsource__isnull=False),  # <- filter subsource is null
                name="unique_subsource"
            ),
            models.UniqueConstraint(
                fields=["parent", "source"],
                condition=models.Q(subsource__isnull=True),
                name="unique_source",
            ),
        ]
类MyObject(ModelBase):
父项=…#强制性的
来源=…#强制性的
子资源=…#可选择的
类元:
约束=[
模型.唯一约束(
字段=[“父”、“源”、“子源”],

condition=models.Q(subsource_uuisnull=False),#我认为解决方案是使用condition创建两个约束

class MyObject(ModelBase):
    parent=... # mandatory
    source=... # mandatory
    subsource=... # optional

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["parent", "source", "subsource"],    
                condition=models.Q(subsource__isnull=False),  # <- filter subsource is null
                name="unique_subsource"
            ),
            models.UniqueConstraint(
                fields=["parent", "source"],
                condition=models.Q(subsource__isnull=True),
                name="unique_source",
            ),
        ]
类MyObject(ModelBase):
父项=…#必填项
来源=…#必填项
子资源=…#可选
类元:
约束=[
模型.唯一约束(
字段=[“父”、“源”、“子源”],

条件=models.Q(子资源为空=False),#你能看一看添加这些约束的迁移生成了什么吗?添加了,但需要一点翻译
dsflink
=>
my_obj
,并且
app_name
macrovars
,乍一看,它似乎从未添加第二个唯一约束?你能看一看迁移是什么吗添加了这些约束?添加了,但需要一些翻译
dsflink
=>
my_obj
,并且
app_name
macrovars
,乍一看,它似乎从未添加第二个唯一约束?现在是两个验证没有被提出(我更新了sql迁移输出)但是我怀疑
condition
会删除Django级别的验证constraint@Sebabouche我在本地进行了检查,它按预期工作。现在没有引发两个验证(我更新了sql迁移输出)但是我怀疑
condition
会删除Django级别的验证constraint@Sebabouche我在当地检查过,它按预期工作。