Класс When
Класс When представляет собой условное выражение, которое используется в сочетании с классом Case для создания условных конструкций в запросах Django. Он позволяет задать условие и соответствующее ему значение, которое будет применено, если условие выполняется. Класс When применяется внутри агрегаций или аннотаций для условной обработки данных.
Основные параметры конструктора When:
-
condition - условие, которое проверяется для каждой записи. Может быть объектом
Qили простым условием сравнения. - then - значение, которое будет возвращено, если условие истинно. Может быть конкретным значением или выражением.
Класс When всегда используется внутри класса Case, который объединяет несколько условий и определяет порядок их проверки.
Синтаксис
from django.db.models import When, Case
When(condition, then=value)
Пример . Использование с аннотацией
Давайте создадим запрос, который добавляет статус пользователя на основе его возраста:
from django.db.models import When, Case, Value, CharField
from myapp.models import User
users = User.objects.annotate(
age_status=Case(
When(age__lt=18, then=Value('minor')),
When(age__gte=18, then=Value('adult')),
default=Value('unknown'),
output_field=CharField()
)
)
for user in users:
print(f"{user.name}: {user.age_status}")
Результат выполнения кода:
"John: minor"
"Jane: adult"
"Bob: adult"
Пример . Использование с агрегацией
Рассмотрим подсчет количества пользователей по категориям с использованием условных выражений:
from django.db.models import When, Case, Count, Q
from myapp.models import User
result = User.objects.aggregate(
minors=Count(
Case(
When(age__lt=18, then=1),
default=None,
output_field=IntegerField()
)
),
adults=Count(
Case(
When(age__gte=18, then=1),
default=None,
output_field=IntegerField()
)
)
)
print(result)
Результат выполнения кода:
{"minors": 15, "adults": 85}
Пример . Использование с несколькими условиями
Создадим более сложное условное выражение, которое классифицирует пользователей по нескольким возрастным группам:
from django.db.models import When, Case, Value, CharField
from myapp.models import User
users = User.objects.annotate(
age_group=Case(
When(age__lt=13, then=Value('child')),
When(age__range=(13, 17), then=Value('teenager')),
When(age__range=(18, 59), then=Value('adult')),
When(age__gte=60, then=Value('senior')),
default=Value('unknown'),
output_field=CharField()
)
)
for user in users:
print(f"{user.name}: {user.age_group}")
Результат выполнения кода:
"Alice: child"
"Mike: teenager"
"Sarah: adult"
"Tom: senior"
Пример . Использование с вычисляемыми значениями
Используем класс When для условного изменения числовых полей:
from django.db.models import When, Case, F, Value, FloatField
from myapp.models import Product
products = Product.objects.annotate(
discounted_price=Case(
When(price__gt=100, then=F('price') * 0.9),
When(price__gt=50, then=F('price') * 0.95),
default=F('price'),
output_field=FloatField()
)
)
for product in products:
print(f"{product.name}: {product.discounted_price}")
Результат выполнения кода:
"Laptop: 900.0"
"Keyboard: 47.5"
"Mouse: 25.0"