【问题标题】:How do I write a Django query that does date math when executed as PostGres SQL?如何编写作为 PostGres SQL 执行时执行日期数学的 Django 查询?
【发布时间】:2020-01-04 03:20:58
【问题描述】:

我正在使用 Django 和 Python 3.7。我正在编写要在 PostGres 9.4 db 上运行的 Django 查询,但无法弄清楚如何形成我的表达式包装器,以便将秒数(整数)添加到现有日期列。我尝试了以下

hour_filter = ExtractHour(ExpressionWrapper(
            F("article__created_on") + timedelta(0,
                                                 F("article__websitet__avg_time_in_seconds_to_reach_ep")),
            output_field=models.DateTimeField)
        ),
)

但我得到了错误

unsupported type for timedelta seconds component: F

有什么想法可以重写我的 ExpressionWrapper 以在 PostGres 查询中进行日期数学运算吗?

编辑;这里是模型和相关字段...

class Website(models.Model):
    ...
    avg_time_in_seconds_to_reach_ep = models.FloatField(default=0, null=True)


class Article(models.Model):
    objects = ArticleManager()
    website = models.ForeignKey(Website, on_delete=models.CASCADE, related_name='articlesite')

【问题讨论】:

  • 您是否尝试过将F(...) 表达式返回的值转换为intfloat?例如:... + timedelta(0, int(F("article_websitet__avg_time_in_seconds_to_reach_ep")), ...
  • @Dave 你能告诉我们相关的模型吗?
  • @Caleb,我编辑了我的问题以包括模型及其相关字段。

标签: django python-3.x postgresql datetime


【解决方案1】:

你可以添加database functions to Django,为此你可以在postgres中为INTERVAL statement添加一个函数

class IntervalSeconds(Func):

    function = 'INTERVAL'
    template = "(%(expressions)s * %(function)s '1 seconds')"

然后您可以在查询中使用此函数将秒数添加到日期时间

YourModel.objects.annotate(
    attr=ExpressionWrapper(
        F("article__created_on") + IntervalSeconds(F("article__websitet__avg_time_in_seconds_to_reach_ep")),
        output_field=models.DateTimeField()
    ),
)

IntervalSeconds 函数的输出是 1 秒 Postgres interval 乘以传递给它的字段。这可以从时间戳中添加和减去。你可以创建一个通用的Interval 函数,它不仅需要几秒钟,这有点复杂

需要ExpressionWrapper 才能将结果转换为日期时间对象

【讨论】:

  • 谢谢,试一试。在我的 ExpressionWrapper 中,我输入了 'F("article__created_on") + IntervalSeconds(F("article__website__avg_time_in_seconds_to_reach_ep")' 但得到了错误,“invalid input syntax for type interval: ""articlesum_website"."avg_time_in_seconds_to_reach_ep" seconds" LINE 1: .. .FROM ("articlesum_article"."created_on" + INTERVAL '"articlesu...'
  • 用更好的功能更新了答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多