在 django 过滤器中使用 dateadd
Using dateadd in django filter
我有一个按开始日期和持续时间(以天为单位)定义订阅期的模型:
class SubscriptionProduct(models.Model):
start_date = models.DateField()
duration = models.IntegerField()
我需要能够过滤当前活跃的订阅,例如start_date < 现在 < start_date+持续时间
我找不到 django 的方法。我可以使用原始 SQL 语句,这些语句使用 postgres 的 DATEADD 等效于 INTERVAL 但我更愿意使用内置的和非数据库特定的东西。
我假设理想情况下我正在寻找 dateadd 注释方法。类似于:
SubscriptionProduct.objects.annotate(end_date=DateAdd('start_date','duration').filter(start_date__lt=datetime.now, end_date__gte=datetime.now)
我最终编写了一个自定义 Func 表达式,它完全符合我的要求。
这是非常 Postgresql 特定的,有点 hacky 但它有效,即使在比上面说明的更复杂的查询中使用。
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()
请注意,我必须使用 arg_joiner 技巧才能在子选择表达式中使用时正确解析两个字段名称
这是 MySQL 的版本:
from django.db.models import Func, DateTimeField
class DateAdd(Func):
function = 'DATE_ADD'
template = "%(function)s(%(expressions)s, INTERVAL %(days)i DAY)"
output_field = DateTimeField()
然后
queryset.annotate(days_added=DateAdd(f'date_field_name', days=1))
我有一个按开始日期和持续时间(以天为单位)定义订阅期的模型:
class SubscriptionProduct(models.Model):
start_date = models.DateField()
duration = models.IntegerField()
我需要能够过滤当前活跃的订阅,例如start_date < 现在 < start_date+持续时间
我找不到 django 的方法。我可以使用原始 SQL 语句,这些语句使用 postgres 的 DATEADD 等效于 INTERVAL 但我更愿意使用内置的和非数据库特定的东西。
我假设理想情况下我正在寻找 dateadd 注释方法。类似于:
SubscriptionProduct.objects.annotate(end_date=DateAdd('start_date','duration').filter(start_date__lt=datetime.now, end_date__gte=datetime.now)
我最终编写了一个自定义 Func 表达式,它完全符合我的要求。 这是非常 Postgresql 特定的,有点 hacky 但它有效,即使在比上面说明的更复杂的查询中使用。
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()
请注意,我必须使用 arg_joiner 技巧才能在子选择表达式中使用时正确解析两个字段名称
这是 MySQL 的版本:
from django.db.models import Func, DateTimeField
class DateAdd(Func):
function = 'DATE_ADD'
template = "%(function)s(%(expressions)s, INTERVAL %(days)i DAY)"
output_field = DateTimeField()
然后
queryset.annotate(days_added=DateAdd(f'date_field_name', days=1))