'Is it possible to use CheckConstraint on model instance in the django shell?
I have a model and want to apply a constraint on it to ensure only sensible values get to be stored in the model.
The model along with the constraint I am using looks somewhat like this (simplified)
from django.db import models
class Task(models.Model):
ACTION_CHOICES = (
('UnderWay', 'UnderWay'),
('Processed', 'Processed'),
('Entrusted', 'Entrusted')
)
action = models.CharField(max_length=20, default='UnderWay', choices=ACTION_CHOICES)
entrusted_to = models.CharField(max_length=20, help_text='Name of the department/person entrusted to')
# some other fields
class Meta:
constraints = [
models.CheckConstraint(
check=(
(models.Q(action='Entrusted') & (models.Q(entrusted_to__isnull=False) | ~models.Q(entrusted_to=''))) |
((models.Q(action='UnderWay') | models.Q(action='Processed')) & (models.Q(entrusted_to__isnull=True) | models.Q(entrusted_to='')))
), #more complex conditions in actual
name='constraint_on_et'
)
]
def __str__(self):
return f'{self.id} - {self.action}'
Makemigrations and migrate ran successfully. But, when I try to create new instances through the shell, the constraint fails in cases that weren't meant to be. I looked at the coded constraint again and it looks fine to me.
So, I tried to break the constraint(constraint_on_et) into simpler conditions to see which one actually fails. As the table is already populated, I am not able to check some specific parts of the constraint(they are always meant to fail on current data).
Out of curiosity, I thought if I could apply a CheckConstraint, directly on a single instance of the model stored in the database rather than applying it on the whole model. On the shell, I was able to easily create a CheckConstraint object like:
c = models.CheckConstraint(
check=(
(models.Q(action='Entrusted') & (models.Q(entrusted_to__isnull=False) | ~models.Q(entrusted_to='')))
),
name='temp_constraint'
)
But, after this, I couldn't see a way to apply this on a Task instance. Looked over the internet and into the implementation of CheckConstraint, but there doesn't seem to be a way for it.
So, my question is, is there any way I could achieve the following? If not, are there any alternatives I could use?
I can save a copy of the current database and test on a separate clean one, but that might not be always feasible.
Note: I am using Django 3.2.10 with db.sqlite3 as the current database.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
