Это немного хакерски, но работает. Вам необходимо конвертировать now
в DateTimeField
. Результат будет в DurationField
- стандартно для timedelta. Для order
мы будем использовать Case
, чтобы проверить, находимся ли мы в выбранной длительности, а затем отсортируем ее.
Я специально изменяю начальный порядок Articles
, чтобы проверить порядок.
from datetime import timedelta
from django.test import TestCase
from django.db.models import ExpressionWrapper, F, Value, Case, When
from django.db.models.fields import DateTimeField, DurationField, BooleanField
from django.utils import timezone
from .models import Article
class ArticleTestCase(TestCase):
def test_days_since_creation(self):
now = timezone.now()
order_in_variants = [
timedelta(days=0),
timedelta(days=7),
timedelta(days=14),
timedelta(days=21),
timedelta(days=28),
]
objects_data = [
Article(
title='Crkp',
creation_date=(now - timedelta(days=14)) # 14 days ago
),
Article(
title='Alrp',
creation_date=(now - timedelta(days=5)) # 5 days ago
),
Article(
title='Bopp',
creation_date=(now - timedelta(days=7)) # 7 days ago
),
]
Article.objects.bulk_create(objects_data)
article_set = Article.objects.all().annotate(
days_since_creation=ExpressionWrapper(
Value(now, DateTimeField()) - F('creation_date'),
output_field=DurationField()
)
).annotate(
order=Case(
When(days_since_creation__in=order_in_variants, then=Value(False)),
default=Value(True),
output_field=BooleanField(),
)
).order_by('order')
for article in article_set:
print(article.days_since_creation.days, article.order)
# 14 False
# 7 False
# 5 True
Вы также можете проверить, что days_since_creation
в диапазоне, а не точно 7-дневная разница. Делает это еще хуже, но все же:
order_in_variants = [
(timedelta(days=0), timedelta(days=0, hours=23, minutes=59, seconds=59, microseconds=999999)),
(timedelta(days=7), timedelta(days=7, hours=23, minutes=59, seconds=59, microseconds=999999)),
(timedelta(days=14), timedelta(days=14, hours=23, minutes=59, seconds=59, microseconds=999999)),
(timedelta(days=21), timedelta(days=21, hours=23, minutes=59, seconds=59, microseconds=999999)),
(timedelta(days=28), timedelta(days=28, hours=23, minutes=59, seconds=59, microseconds=999999)),
]
# ...
order=Case(
When(days_since_creation__range=order_in_variants[0], then=Value(False)),
When(days_since_creation__range=order_in_variants[1], then=Value(False)),
When(days_since_creation__range=order_in_variants[2], then=Value(False)),
When(days_since_creation__range=order_in_variants[3], then=Value(False)),
When(days_since_creation__range=order_in_variants[4], then=Value(False)),
default=Value(True),
output_field=BooleanField(),
)