When I delete an object ('item') in my Django app, a related object (in another table) that points to it via a foreign key should also get deleted due to its "on_delete=models.CASCADE" setting. But the cascade delete is failing because of a check constraint on the related model:
MySQLdb.OperationalError: (3819, "Check constraint 'item_or_container' is violated.")
My question is, why would a check constraint be triggered on a delete? Does Django modify the record somehow before deletion?
The record in question does pass the constraint, and if I just delete that record directly it works as expected; it only fails during a cascade delete.
The "violated" constraint is as follows:
models.CheckConstraint(check=Q(item__isnull=False) ^ Q(is_container=True), name='item_or_container')
(Which is an XOR ensuring that an object can EITHER have an assigned item OR be a container - not both.)
My expectation is that both records should simply be deleted. Thank you for your help!
Edit: Here is the 'want' model with the foreign key to the 'item' model:
class Want(models.Model): # items that a trader wishes to get
event = models.ForeignKey(Event, on_delete=models.CASCADE)
trader = models.ForeignKey(Trader, on_delete=models.CASCADE)
item = models.ForeignKey(Item, null=True, blank=True, default=None, on_delete=models.CASCADE)
value = models.PositiveIntegerField(default=1, blank=False, validators=[MinValueValidator(1), MaxValueValidator(10)])
offer_price = models.DecimalField(max_digits=19, decimal_places=4, default=0, blank=True, verbose_name="Cash Offer")
is_container = models.BooleanField(default=False, blank=True)
container_name = models.CharField(max_length=100, blank=False)
num_contained = models.PositiveIntegerField(default=0, blank=False)
container_limit_num = models.PositiveIntegerField(default=0, blank=False)
contained_by = models.ForeignKey('self', default=None, null=True, blank=True, on_delete=models.CASCADE)
class Meta:
constraints = [
models.UniqueConstraint(fields=['trader', 'item'], name='unique_want'),
models.CheckConstraint(check=Q(item__isnull=False) ^ Q(is_container=True), name='item_or_container'),
]
(The 'item' model is very simple, with no 'Meta' section, and does not know/care about 'want'.)
I am using Django 4.2.4, and mysqlclient 2.2.0.