Аннотирование специфических атрибутов поля времени даты - Не удается преобразовать ключевое слово 'toordinal' в поле. Объединение по 'created_at' не разрешено

Я разрабатываю систему оценки постов на сайте. Она учитывает другие реляционные поля (комментарии, просмотры и реакции_эмоджи), чтобы иметь более глубокий способ упорядочивания результатов.

Но поскольку нежелательно иметь на первой странице популярные, но слишком старые посты, я решил учитывать время создания поста.

Проблема в том, что значение DateTime слишком точное, и упорядочивание по нему полностью игнорирует систему оценок и возвращает простую хронологическую ленту.

В процессе тестирования некоторых решений, я попробовал встроенную функцию toordinal, чтобы иметь одно значение, представляющее дни, прошедшие с 1 января 1-го года. Моя идея заключалась в конкатенации этого значения с post_hour и результатом (post_minute // 14). Таким образом, в течение 14 минут все посты будут упорядочены исключительно по их оценкам. Это выглядит достаточно хорошо, и любые корректировки будут просты для внесения.

Посмотрев некоторые посты SO и документацию Django, я обнаружил, что могу сделать это, передав атрибут, к которому я пытался получить доступ, с помощью дундера внутри выражения F:

posts = Post.objects.all().annotate(
            score=((F("view_count")/20) + (Count("post_emojis")/10) + (Count("post_comments")/5)),
            ordinal_time=(F('created_at__toordinal'))
        )        

Выдает следующую ошибку:

Cannot resolve keyword 'toordinal' into field. Join on 'created_at' not permitted.

Это первый раз, когда я использую annotate, поэтому я немного запутался.

РЕДИТ: Понял! Я опубликую это как ответ после дополнительного тестирования и уверенности, что это не слишком замедлит выполнение запросов.

posts = Post.objects.all().annotate(
            score=((F("view_count")/20) + (Count("post_emojis")/10) + (Count("post_comments")/5)),
            year=(Extract(expression="created_at", lookup_name='year')),
            month=(Extract(expression="created_at", lookup_name='month')),
            day=(Extract(expression="created_at", lookup_name='day')),
            hour=(Extract(expression="created_at", lookup_name='hour')),
            minute=(Extract(expression="created_at", lookup_name='minute')),
            divided_minute=(Cast((F("minute") / 14), output_field=IntegerField())),
            time=Concat("year", "month", "day", "hour", "divided_minute")
        )

Вернуться на верх