Как добавить упорядочивание к условиям Case, When в django
Имеется два поля: start_date и end_date. (DateField).
Стандартный для сортировки.
- Both start_date and end_date are empty values. (start_date = Null, end_date = Null)
- Start_date Most recently and end_date is empty values (start_date = not null, end_date = Null)
- If both start_date and end_date have values, end_date most recently (start_date = not Null, end_date = not Null)
- If both start_date and end_date have values, start_date most recently (start_date = not Null, end_date = not Null)
Ex) Я хочу
start end
1. null null
2. null null
3. 2021-10-01 null
4. 2021-09-01 null
5. 2021-09-15 21-09-20
6. 2021-09-01 2021-09-20
7. 2021-09-01 2021-09-15
Я пытался
Model.objects.annotate(
order1=Case(
When(Q(start_date__isnull=True) & Q(end_date__isnull=True), then=0),
When(Q(start_date__isnull=False) & Q(end_date__isnull=True), then=1), # how to order by start_date ??
When(Q(start_date__isnull=False) & Q(end_date__isnull=False), then=2), # how to order by end_date ??
output_field=IntegerField()
),
).order_by('order1')
результат
start end
1. null null
2. null null
3. 2021-09-01 null # change 3, 4
4. 2021-10-01 null
5. 2021-09-15 21-09-20
6. 2021-09-01 2021-09-20
7. 2021-09-01 2021-09-15
Как я могу решить сложную задачу order by в django?
Я нашел способ работы, хотя скорость медленная. Он не был полностью проверен.
Model.objects.annotate(
order1=Case(When(Q(start_date__isnull=True) & Q(end_date__isnull=True), then=1), default=0, output_field=IntegerField())
).annotate(
order2=Case(When(Q(start_date__isnull=False) & Q(end_date__isnull=True), then=Max('start_date')), output_field=DateField())
).annotate(
order3=Case(When(Q(start_date__isnull=False) & Q(end_date__isnull=False), then=Max('end_date')), output_field=DateField())
).order_by(
F('order1').desc(nulls_last=True), F('order2').desc(), F('order3').desc(), '-start_date'
)
Я не думаю, что это идеальное решение, но я делюсь им, потому что оно может кому-то помочь.
Если есть лучший способ, пожалуйста, поделитесь им.