I am trying to extend a model in an Django App. The only problem I have is that I need to extend the model constraints as well and that does not work properly.
This is the original constraint for the object in models.py:
models.CheckConstraint(
check=(
models.Q(inventory_item__isnull=True, device_type__isnull=False)
| models.Q(inventory_item__isnull=False, device_type__isnull=True)
),
name="At least one of InventoryItem or DeviceType specified.",
)
I have tried to extend it like that:
models.CheckConstraint(
check=(
models.Q(inventory_item__isnull=True,
device_type__isnull=False,
module_type__isnull=False)
| models.Q(inventory_item__isnull=False,
device_type__isnull=True,
module_type__isnull=False)
| models.Q(inventory_item__isnull=False,
device_type__isnull=False,
module_type__isnull=True)
),
name="At least one of InventoryItem, ModuleType or DeviceType specified.",
),
This is how this looks in the migration:
migrations.AddConstraint(
model_name='hardwarelcm',
constraint=models.CheckConstraint(check=models.Q(models.Q(('device_type__isnull', False), ('inventory_item__isnull', True), ('module_type__isnull', False)), models.Q(('device_type__isnull', True), ('inventory_item__isnull', False), ('module_type__isnull', False)), models.Q(('device_type__isnull', False), ('inventory_item__isnull', False), ('module_type__isnull', True)), _connector='OR'), name='At least one of InventoryItem or ModelType or DeviceType specified.'),
)
My problem is that I tried all combinations and it fails every time, but I can see from the error message that only one value is set and the other are Null.
DETAIL: Failling row contains (3, null, 1, null)
Is there some limitation with Q objects that I don't understand? I have tried to read the Django documentation, but could not figure out what the problem is.
CodePudding user response:
Your condition does the opposite: it requires that two items are not None
. You should make a check with:
from django.db.models import Q
models.CheckConstraint(
check=Q(inventory_item=None, device_type=None, module_type__isnull=False) |
Q(inventory_item=None, device_type__isnull=False, module_type=None) |
Q(inventory_item__isnull=False, device_type=None, module_type=None),
name='At least one of InventoryItem, ModuleType or DeviceType specified.'
)
This means that you can specify exactly one. If you want to specify at least one, you can work with:
from django.db.models import Q
models.CheckConstraint(
check=Q(
inventory_item__isnull=False,
device_type__isnull=False,
module_type__isnull=False,
_connector=Q.OR
),
name='At least one of InventoryItem, ModuleType or DeviceType specified.'
)