I have a model that defines subscription periods by start date and duration (in days):
class SubscriptionProduct(models.Model):
start_date = models.DateField()
duration = models.IntegerField()
I need to be able to filter subscriptions that are currently active, e.g. start_date < now < start_date+duration
I can't find the django way to do it. I can use raw SQL statements that use postgres' DATEADD equivalent of INTERVAL but i'd prefer to use something builtin and non db specific.
I assume ideally i'm looking for a dateadd annotation method. Something like:
SubscriptionProduct.objects.annotate(end_date=DateAdd('start_date','duration').filter(start_date__lt=datetime.now, end_date__gte=datetime.now)
I ended up writing a custom Func expression that does exacly what I was looking for. This is very Postgresql specific and a bit hacky but it works, even when used in more complex queries than the one illustrated above.
class DateAdd(Func):
"""
Custom Func expression to add date and int fields as day addition
Usage: SubscriptionProduct.objects.annotate(end_date=DateAdd('start_date','duration')).filter(end_date__gt=datetime.now)
"""
arg_joiner = " + CAST("
template = "%(expressions)s || ' days' as INTERVAL)"
output_field = DateTimeField()
Note that I had to do the arg_joiner trick in order for both field names to be resolved properly when used in subselect expressions
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With