Reputation: 10916
I need to filter objects older than X
number of days. I realize this question exists here: django filter older than day(s)?
However, I not trying to do exactly that, since the number of days, in my case lives inside the model:
class Post(models.Model):
title = models.CharField(max_length=200)
description = models.CharField(max_length=500)
createdAt = models.DateTimeField(default=datetime.now, blank=True)
plan = models.ForeignKey(Plan) # This model has the number of days
This is the query I have so far:
EDIT: I changed the days.plan part for the_post.plan.days
Meaning that the number of days that I'm using to compare is in each post's plan
field.
Post.objects.filter(createdAt__lte=datetime.now() - timedelta(days=the_post.plan.days))
Note the plan.days
part of the query. How can I reference the_post.plan.days
for this query? Is it possible?
Upvotes: 4
Views: 2480
Reputation: 1399
Assuming Postgres database:
table_post = Post._meta.db_table
table_plan = Plan._meta.db_table
old_posts = Post.objects.select_related('plan')\
.extra(where=["%s.created_at <= NOW() - INTERVAL '1 day' * %s.days"
% (table_post, table_plan)])
Upvotes: 1
Reputation: 5948
With a small tweak in your Plan model, it is indeed possible to do what you want.
First of all, you'll need to change your Plan days
field, which is probably an IntegerField
, to DurationField.
Now the catch is that we have to use ExpressionWrapper to achieve the exact same result inside Postgres as the result you'd achieve in Python if you were to get the plan in a separate query.
Finally, your query should be something like:
from django.db.models import F, ExpressionWrapper, DateTimeField
from django.utils import timezone
Post.objects.annotate(target_date=ExpressionWrapper(timezone.now() - F('plan__days'), output_field=DateTimeField())).filter(createdAt__lte=F('target_date'))
Upvotes: 2
Reputation:
For me you must first grab the plan object.
plan = Plan.objects.filter(...)
and then reference the days
Post.objects.filter(createdAt__lte=datetime.now() - timedelta(days=plan.days))
Upvotes: 0