Есть ли в Django способ упорядочить модель с помощью "пользовательской логики фильтрации"?
В настоящее время у меня возникла проблема в личном проекте, который включает в себя упорядочивание по 2 пользовательским полям (limit_date и priority). Предположим, что модель выглядит следующим образом:
PRIORITY_CHOICES = [
("red", "Red"),
("yellow", "Yellow"),
("green", "Green")
]
class Todo(models.Model):
limit_date = models.DateField()
priority = models.CharField(choices=PRIORITY_CHOICES, max_length=15,
blank=False, null=True)
Предположим, я хочу упорядочить их, следуя следующей логике:
if <current_todo>.priority == 'red':
priority_scale = 3
elif <current_todo>.priority == 'yellow':
priority_scale = 2
else:
priority_scale = 1
priority_scale_with_date = <current_todo>.limit_date - datetime.today() * (<current_todo>.priority_scale)
Я знаю, что могу делать некоторые вещи с "условными выражениями" для получения приоритетов в качестве значений, например:
Todo.objects.annotate(
priority_scale=Case(
When(priority='red',
then=Value(3)),
When(priority='yellow',
then=Value(2)),
When(priority='green',
then=Value(1)),
default=Value(0),
output_field=models.IntegerField())).order_by('-priority_scale', 'limit_date')
Но я не знаю, как я могу соединить их все "вместе". Допустим, объект с приоритетом "красный" (значение 3), у которого осталось два дня, и другой объект с приоритетом "зеленый" (значение 1), у которого остался один день. Их приоритеты будут примерно такими: first_obj = 1 * 3 = 3 (дни до limit_date и 'priority_scale') second_obj = 2 * 1 = 2 (дни до limit_date и 'priority_scale'). Что я хочу, так это упорядочить их с "пересечением" 'priority_scale' и 'limit_date'. Я очень запутался и прошу прощения за этот очень плохой текст.
Я бы предположил, что это случай для хранения значения на уровне базы данных как целого числа, и создания метода модели для представления его представлениям и пользователям как "красный" и т.д.
PRIORITY_CHOICES = [
(3, "Red"),
(2, "Yellow"),
(1, "Green"),
(0, "Null")
]
priority = models.IntegerField(choices=PRIORITY_CHOICES, max_length=15,
) # default=0 ?
In views `todo_instance.get_priority_display()` will return `"Red"` etc.
Где я не могу помочь, так это как получить количество оставшихся дней на уровне базы данных, чтобы можно было вычислить значение для annotate и order_by с помощью F-выражений. (Я просмотрел функции базы данных , но не могу сразу понять, как сделать разницу дат. Я думаю "это должно быть возможно"...)