CheckConstraint в модели Django не запускается в unittest.TestCase (ошибка утверждения: ошибка целостности не вызывается)

У меня есть класс Model с рядом ограничений, которые я пытаюсь протестировать, и я не могу заставить эти ограничения возвращать IntegrityError при тестировании. Класс выглядит следующим образом:

from django.db import models
from django.db.models import CheckConstraint, Q, UniqueConstraint


class Products(models.Model):
    sku = models.CharField(primary_key=True, max_length=8)
    barcode = models.CharField(unique=True, max_length=14, blank=True, null=True)
    name = models.TextField(blank=True, null=True)
    rrp = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    status = models.TextField()
    manufacturer = models.TextField(blank=True, null=True)
    brand = models.TextField(blank=True, null=True)
    country_of_origin = models.TextField(blank=True, null=True)
    last_updated = models.DateField(blank=True, null=True)
    date_published = models.DateField(blank=True, null=True)
    exclusive = models.BooleanField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'product'
        constraints = [
            CheckConstraint(
                condition=Q(status__in=['Draft', 'Live', 'Discontinued']),
                name='check_status',
                violation_error_message="status field must be on of the following: 'Draft', 'Live', 'Discontinued'",
            ),
            CheckConstraint(
                condition=~(Q(date_published__isnull=False) & Q(status__in=['Draft', 'Discontinued'])),
                name='check_date_published',
                violation_error_message="Product with status 'Draft' or 'Discontinued' cannot have a date_published value"
            ),
            UniqueConstraint(fields=['barcode'], name='unique_barcode'),
            UniqueConstraint(fields=['sku', 'exclusive'], name='unique_sku_and_exclusive'),
            UniqueConstraint(fields=['sku', 'status'], name='unique_sku_and_status')
        ]

Значение "управляемый" заменяется на 0001_initial.py при запуске тестов. IntegrityError, который я использую, относится к django.db.utils, а не к sqlite3, однако метод save() изначально не возвращает никаких исключений, поэтому проблема не связана с неправильной версией IntegrityError.

from django.db.utils import IntegrityError
from django.test import TestCase

from .models import Products


class ProductTestCase(TestCase):
    def setUp(self):
        self.product = Products.objects.create(
            sku = '12345678',
            barcode = '5666777888999',
            name = 'Test Product 1',
            rrp = 999,
            status = 'Live',
            manufacturer = '',
            brand = 'Test Brand',
            country_of_origin = 'China',
            last_updated = '2025-01-01',
            date_published = '2025-01-01',
            exclusive = False
    )

    def test_invalid_product_status_not_null(self):
        """Test product can't be made with an invalid status value"""
        self.product.status = 'WrongStatus'
        with self.assertRaises(IntegrityError):
            self.product.save()

Я попытался просто создать объект Products в предложении with, содержащий только sku и status, я попытался ввести ограничения как внутри, так и за пределами списка ограничений в meta, но я просто не могу заставить CheckConstraint сработать. Я неправильно понимаю, когда должны срабатывать ограничения? Или я неправильно пишу Q-объекты?

constraints Выполняется базой данных, поэтому Django преобразует CheckConstraint в CHECK status IN ('Draft', 'Live', 'Discontinued').

Но вы также сказали managed = False, это означает, что Django не должен вносить изменения в структуру таблицы базы данных. Таким образом, он не будет добавлять / удалять поля / ограничения/…

В результате добавление элементов в constraints действительно не будет иметь значения, вам придется вручную добавить их в базу данных.

Вернуться на верх