根据 Django 中的间隔过滤数据
Filter data based on intervals in Django
我有以下型号:
class MyModel(models.Model):
due = models.DateTimeField(null=True)
max_days_before_due = models.IntegerField()
我想过滤掉过期的实例或行,即。当 due
减去 max_days_before_due
是过去时。我正在使用这个查询:
current_date = timezone.now()
MyModel.objects.annotate(
counted_days=Case(
When(
due__isnull=False,
then=ExtractDay(F('due')-current_date)
),
default=0,
output_field=IntegerField()
)
).filter(
max_days_before_due__lt=F('counted_days')
)
我收到此错误:
django_1 | File "/usr/local/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
django_1 | return self.cursor.execute(sql, params)
django_1 | django.db.utils.ProgrammingError: function pg_catalog.timezone(unknown, interval) does not exist
django_1 | LINE 1: ... '2020-08-26T15:03:11.111165+00:00'::timestamptz) AT TIME ZO...
django_1 | ^
django_1 | HINT: No function matches the given name and argument types. You might need to add explicit type casts.
当我从注释中删除减法时,错误没有显示,但我需要能够计算时间增量。否则,如果我将 due
设置为 2020-08-30
并且 current_date
是 2020-08-26
它 returns 30 在 counted_days
字段中而不是 4 .
我一直在尝试使用 and these docs 作为参考。我在版本 10 中使用 PostgreSQL,在版本 1.11 中使用 Django,Python 3.4.
编辑
看起来这个任务应该很简单,使用简单的 SQL:
postgres=# SELECT DATE '2020-08-26' + 10;
?column?
------------
2020-09-05
也许有更简单的方法。
经过几个小时的调试后,我设法发现了问题所在以及解决方法,所以我们开始吧。
我保存在数据库中的字段是“带时区的时间戳”。
我设法在 postgres 中重现了 sql 中的错误。选择 TIMESTAMP
并从中减去一个整数时,出现与 Django 日志中显示的相同的错误:
postgres=# SELECT TIMESTAMP '2020-08-26 01:01:00.123456-01:00' + 10 > DATE '2020-09-01';
ERROR: operator does not exist: timestamp without time zone + integer
LINE 1: ...ECT TIMESTAMP '2020-08-26 01:01:00.123456-01:00' + 10 > DAT...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
正如我在问题更新中所说,从日期对象中添加或减去整数相当容易:
postgres=# SELECT DATE '2020-08-26 01:01:00.123456-01:00' + 10 > DATE '2020-09-01';
?column?
----------
t
(1 row)
这建议在注释中使用适当的转换:
MyModel.objects.annotate(due_date=Case(
When(
due__isnull=False,
then=Cast('due', output_field=DateField()) - F('max_days_before_due')
),
default=None,
output_field=DateTimeField()
).filter(due_date__gt=current_date)
和中提琴:
pprint(my_model_query.values('due', 'max_days_before_due', 'due_date')))
Returns:
<MyModelQuerySet [{'due': datetime.datetime(2020, 8, 20, 9, 31, 25, tzinfo=<UTC>), 'max_days_before_due': 30, 'due_date': datetime.date(2020, 7, 21)}]>
我有以下型号:
class MyModel(models.Model):
due = models.DateTimeField(null=True)
max_days_before_due = models.IntegerField()
我想过滤掉过期的实例或行,即。当 due
减去 max_days_before_due
是过去时。我正在使用这个查询:
current_date = timezone.now()
MyModel.objects.annotate(
counted_days=Case(
When(
due__isnull=False,
then=ExtractDay(F('due')-current_date)
),
default=0,
output_field=IntegerField()
)
).filter(
max_days_before_due__lt=F('counted_days')
)
我收到此错误:
django_1 | File "/usr/local/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
django_1 | return self.cursor.execute(sql, params)
django_1 | django.db.utils.ProgrammingError: function pg_catalog.timezone(unknown, interval) does not exist
django_1 | LINE 1: ... '2020-08-26T15:03:11.111165+00:00'::timestamptz) AT TIME ZO...
django_1 | ^
django_1 | HINT: No function matches the given name and argument types. You might need to add explicit type casts.
当我从注释中删除减法时,错误没有显示,但我需要能够计算时间增量。否则,如果我将 due
设置为 2020-08-30
并且 current_date
是 2020-08-26
它 returns 30 在 counted_days
字段中而不是 4 .
我一直在尝试使用
编辑
看起来这个任务应该很简单,使用简单的 SQL:
postgres=# SELECT DATE '2020-08-26' + 10;
?column?
------------
2020-09-05
也许有更简单的方法。
经过几个小时的调试后,我设法发现了问题所在以及解决方法,所以我们开始吧。
我保存在数据库中的字段是“带时区的时间戳”。
我设法在 postgres 中重现了 sql 中的错误。选择 TIMESTAMP
并从中减去一个整数时,出现与 Django 日志中显示的相同的错误:
postgres=# SELECT TIMESTAMP '2020-08-26 01:01:00.123456-01:00' + 10 > DATE '2020-09-01';
ERROR: operator does not exist: timestamp without time zone + integer
LINE 1: ...ECT TIMESTAMP '2020-08-26 01:01:00.123456-01:00' + 10 > DAT...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
正如我在问题更新中所说,从日期对象中添加或减去整数相当容易:
postgres=# SELECT DATE '2020-08-26 01:01:00.123456-01:00' + 10 > DATE '2020-09-01';
?column?
----------
t
(1 row)
这建议在注释中使用适当的转换:
MyModel.objects.annotate(due_date=Case(
When(
due__isnull=False,
then=Cast('due', output_field=DateField()) - F('max_days_before_due')
),
default=None,
output_field=DateTimeField()
).filter(due_date__gt=current_date)
和中提琴:
pprint(my_model_query.values('due', 'max_days_before_due', 'due_date')))
Returns:
<MyModelQuerySet [{'due': datetime.datetime(2020, 8, 20, 9, 31, 25, tzinfo=<UTC>), 'max_days_before_due': 30, 'due_date': datetime.date(2020, 7, 21)}]>