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
действительно не будет иметь значения, вам придется вручную добавить их в базу данных.