I am new to Django and trying to define what should be a simple database CheckConstraint. The intention is to prevent two boolean values, “light” and “pigment”, from both being True. Either one or the other or neither can be True as a valid case. Simple logic, but I can’t seem get the syntax correct. Can someone please show me how to correctly specify this CheckConstraint?
Here is the model:
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
def __str__(self):
return self.name
# this below fails with:
# NameError: name 'light' is not defined
class Meta:
constraints = [
models.CheckConstraint(
check = not (models.Q(light == True) and models.Q(pigment == True)),
name = "light and pigment"
)
]
Your conditions in the constraint aren’t python expressions, they’re positional parameters being passed in to the Q object initializer. (Take a look at Complex Lookups with Q objects.)
Try: ~(models.Q(light=True) & models.Q(pigment=True))
or: models.Q(light__ne=True) | models.Q(pigment__ne=True)
<opinion>
I believe the code looks better if you import the individual components (such as Q) rather than just importing the module.
For example, your code would become:
from django.db.models import (Model, CharField, BoooleanField, ForeignKey,
TextField, Q, CheckConstraint)
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
class Colors(models.Model):
name = CharField(max_length=200, unique=True)
light = BooleanField(default = False)
pigment = BooleanField(default = False)
owner = ForeignKey(User, on_delete=models.PROTECT,
blank = True, null = True)
note = TextField(blank = True)
def __str__(self):
return self.name
# this below fails with:
# NameError: name 'light' is not defined
class Meta:
constraints = [
CheckConstraint(
check = ~ (Q(light=True) & Q(pigment=True)),
name = "light and pigment"
)
]
which I think is far easier to read overall. (That’s assuming I haven’t done something on the fly here to really butcher the syntax beyond recognition.) </opinion>