使用数据库时钟的相对时间的 Django 查询
Django query with relative time using database's clock
我正在尝试查找最近 30 秒内更新的所有 ORM 对象。执行此操作的标准方法是:
reftime = timezone.now() - relativedelta(seconds=30)
queryset = MyModel.objects.filter(updated_at__gte=reftime)
只要所有应用程序服务器 运行 Django 应用程序的时钟都同步,这就可以工作,这听起来很容易,但实际上并非如此。时钟偏差是真实的。
幸运的是,数据库服务器只有一个时钟,我们应该可以将其作为此类事情的最终时钟。 django 在 django.db.models.functions
中有一个名为 Now()
的漂亮对象,它似乎对此类事情应该有所帮助。但我从来没有见过这种方法的任何代码示例,它通过任何数学运算将时间移动大约 30 秒。例如这不起作用:
reftime = django.db.models.functions.Now() - relativedelta(seconds=30)
如何使用相对于 SQL 服务器时钟的时间戳进行 django ORM 查询?
您不应使用 relativedelta
,而应使用 timedelta
[Python-doc],因此:
from datetime import timedelta
from django.db.models.functions import Now
queryset = MyModel.objects.filter(<strong>updated_at__gte=Now()-timedelta(seconds=30)</strong>)
Django 已经实现了从 Now
class 中减去 timedelta
的逻辑,因此为此创建了一个 SQL 表达式。 不是 relativedelta
的情况。
事实上,我们可以显示 Django 使用的查询:
>>> print(Event.objects.filter(updated_at__gte=Now()-relativedelta(seconds=30)).query)
SELECT `app_name_mymodel`.`id`, `app_name_mymodel`.`updated_at` FROM `app_name_mymodel` WHERE `app_name_mymodel`.`updated_at` >= (CURRENT_TIMESTAMP - relativedelta(seconds=+30))
>>> print(Event.objects.filter(updated_at__gte=Now()-timedelta(seconds=30)).query)
SELECT `app_name_mymodel`.`id`, `app_name_mymodel`.`updated_at` FROM `app_name_mymodel` WHERE `app_name_mymodel`.`updated_at` >= (CURRENT_TIMESTAMP - INTERVAL 30000000 MICROSECOND)
对于relativedelta
它只是使用对象的str(…)
,而对于timedelta
对象,它“理解”这种类型,并将其转换为相应的SQL方言等值。
我正在尝试查找最近 30 秒内更新的所有 ORM 对象。执行此操作的标准方法是:
reftime = timezone.now() - relativedelta(seconds=30)
queryset = MyModel.objects.filter(updated_at__gte=reftime)
只要所有应用程序服务器 运行 Django 应用程序的时钟都同步,这就可以工作,这听起来很容易,但实际上并非如此。时钟偏差是真实的。
幸运的是,数据库服务器只有一个时钟,我们应该可以将其作为此类事情的最终时钟。 django 在 django.db.models.functions
中有一个名为 Now()
的漂亮对象,它似乎对此类事情应该有所帮助。但我从来没有见过这种方法的任何代码示例,它通过任何数学运算将时间移动大约 30 秒。例如这不起作用:
reftime = django.db.models.functions.Now() - relativedelta(seconds=30)
如何使用相对于 SQL 服务器时钟的时间戳进行 django ORM 查询?
您不应使用 relativedelta
,而应使用 timedelta
[Python-doc],因此:
from datetime import timedelta
from django.db.models.functions import Now
queryset = MyModel.objects.filter(<strong>updated_at__gte=Now()-timedelta(seconds=30)</strong>)
Django 已经实现了从 Now
class 中减去 timedelta
的逻辑,因此为此创建了一个 SQL 表达式。 不是 relativedelta
的情况。
事实上,我们可以显示 Django 使用的查询:
>>> print(Event.objects.filter(updated_at__gte=Now()-relativedelta(seconds=30)).query) SELECT `app_name_mymodel`.`id`, `app_name_mymodel`.`updated_at` FROM `app_name_mymodel` WHERE `app_name_mymodel`.`updated_at` >= (CURRENT_TIMESTAMP - relativedelta(seconds=+30)) >>> print(Event.objects.filter(updated_at__gte=Now()-timedelta(seconds=30)).query) SELECT `app_name_mymodel`.`id`, `app_name_mymodel`.`updated_at` FROM `app_name_mymodel` WHERE `app_name_mymodel`.`updated_at` >= (CURRENT_TIMESTAMP - INTERVAL 30000000 MICROSECOND)
对于relativedelta
它只是使用对象的str(…)
,而对于timedelta
对象,它“理解”这种类型,并将其转换为相应的SQL方言等值。