Using dateadd in django filter

喜欢而已 提交于 2019-12-10 23:41:39

问题


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)

回答1:


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



来源:https://stackoverflow.com/questions/33981468/using-dateadd-in-django-filter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!