Django conditional expression classes
I recently discovered a really cool Django feature — conditional expression classes that can be used in querysets to mimic if
/else
statements. Here’s an example I’ve adapted from the Django 4.1 documentation:
from django.db.models import When, Q
from my_app.models import Client
"""
We have the model Client, which includes the
fields `account_type` and `name`. The kwarg
`then` takes one of the fields as a string:
"""
When(account_type=Client.GOLD, then='name')
"""
If the name starts with "John" or "George", then
it evaluates to True, i.e. we only get names that
meet those conditions:
"""
When(
Q(name__startswith="John") | Q(name__startswith="Paul"),
then='name'
)
Something quite poetic about it, no?
We can evaluate according to more conditions by adding the the Case()
class to it, which can take multiple When()
arguments:
from django.db.models import Case, Q, When
from my_app.models import Client
When(account_type=Client.GOLD, then='name')
Case(
When(
Q(name__startswith="John") | Q(name__startswith="Paul"),
then='name'
),
When(
Q(name__endswith="Lennon") | Q(name__endswith="McCartney"),
then='name'
)
)
You can probably guess that we are trying to find all clients whose first name is either John or Paul, and whose last name is either Lennon or McCartney.
In the Django source code, you can see that both Case
and When
are based on the Expression
class and see how they are built; Django, after all, is just a program that we use with our programs. It's pretty cool to have reached a point in my career where I'm curious about what goes on behind the scenes of the code that someone else wrote, rather than merely using it. Extending it, if you will.