Django IntegrityError с UniqueConstraint

У меня есть модель с UniqueConstraint на полях: site, name, type, когда status является либо живым, либо черновым.

Однако, когда я создаю 2 объекта с одинаковым сайтом, именем и типом (один с status = live, а другой с status = draft), он выдает эту ошибку:

django.db.utils.IntegrityError: UNIQUE constraint failed: site_config_configuration.site_id, site_config_configuration.name, site_config_configuration.type

Я использовал этот документ для UniqueConstraint: https://docs.djangoproject.com/en/3.2/ref/models/constraints/#uniqueconstraint

Вот моя модель:

class Configuration(models.Model):
    CSS = 'css'
    SECRET = 'secret'
    TYPES = [
        (CSS, 'css'),
        (SECRET, 'secret')
    ]
    LIVE = 'live'
    DRAFT = 'draft'
    HISTORY = 'history'
    STATUSES = [
        (LIVE, 'Live'),
        (DRAFT, 'Draft'),
        (HISTORY, 'History')
    ]
    site = models.ForeignKey(Site, on_delete=models.CASCADE)
    name = models.CharField(max_length=255, blank=False)
    type = models.CharField(
        max_length=255,
        choices=TYPES)
    value = models.JSONField(
        null=True)
    status = models.CharField(
        max_length=20,
        choices=STATUSES)
    created = models.DateTimeField(editable=False, auto_now_add=True)
    modified = models.DateTimeField(editable=False, auto_now=True)

    class Meta(object):
        constraints = [
            models.UniqueConstraint(
                fields=['site', 'name', 'type'],
                condition=(Q(status='draft') | Q(status='live')),
                name='unique config')
        ]

Вот мой простой тест, в котором я создаю 2 объекта, и он выбрасывает django.db.utils.IntegrityError при создании config_draft:

import pytest
from site_config.models import Site, Configuration

@pytest.mark.django_db
def test_configuration_model():
    """
    Tests for Configuration Model
    """
    site = Site.objects.create(domain_name='hello-world.org')
    config_live = Configuration.objects.create(
        site=site,
        name="$cta-button-border",
        type='css',
        value="2px solid #0090c1",
        status='draft',
        structure_version='v1',
        author_email='example@example.com')

    config_draft = Configuration.objects.create(
        site=site,
        name="$cta-button-border",
        type='css',
        value="5px solid #0090c1",
        status='live',
        structure_version='v2',
        author_email='example@example.com')

    assert config.status == 'draft'
    assert str(config) == "Configuration: hello-world.org \"$cta-button-border\""

Я думаю, что вы также должны поместить 'статус' в уникальные поля:

constraints = [
            models.UniqueConstraint(
                fields=['site', 'name', 'type', 'status'],
                condition=(Q(status='draft') | Q(status='live')),
                name='unique config')
        ]
Вернуться на верх