I'm trying to do some complex ordering based on promotions: an article is promoted every 7th day since creation (the articles expire after 30 days).
My approach is to annotate the queryset with the number of days since it was created, but the value of the annotated field (
days_since_creation), in my code, is always 0.
from datetime import timedelta from django.test import TestCase from django.db.models import ExpressionWrapper, F from django.db.models.fields import IntegerField from django.utils import timezone from .models import Article # class Article(models.Model): # title = models.CharField(max_length=150) # creation_date = models.DateTimeField() # # def __str__(self): # return self.title class ArticleTestCase(TestCase): def test_days_since_creation(self): now = timezone.now() objects_data = [ 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( title='Crkp', creation_date=(now - timedelta(days=14)) # 14 days ago ), ] Article.objects.bulk_create(objects_data) article_set = Article.objects\ .annotate( days_since_creation=ExpressionWrapper( now - F('creation_date'), output_field=IntegerField() ) ) for article in article_set: print(article.days_since_creation) # all 3 objects print "0"
I expected the value for each object to be 5, 7, 14 repectively. I even tried
DurationField but that just printed 0:00:00.
After that I would annotate the queryset again with an
order field that has the value 0 if the value of
days_since_past is in
[0, 7, 14, 21, 28,] or 1 otherwise, and then