繁体   English   中英

如何在Django ORM查询中的列中使用timedelta?

[英]How do I use timedelta with a column in my Django ORM query?

我正在使用Django和Python 3.7。 我有以下两种型号...

class Article(models.Model):
    ...
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE, related_name="articles",)
    created_on = models.DateTimeField(default=datetime.now)

class WebPageStat(models.Model):
    ...
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE, related_name="stats", )

    elapsed_time_in_seconds = models.FloatField(default=0)
    score = models.BigIntegerField(default=0)

class Publisher(models.Model):
   name = models.CharField(max_length=100)

   def __str__(self):
       return self.name

我想编写一个Django ORM查询,其中给定发布者和经过的时间(以秒为单位)(WebPageStat记录),我发现所有“ created_on”日期不早于经过的时间(以秒为单位)的文章。 许多人建议在其他帖子中使用“ timedelta”,但这似乎对我不起作用...

Article.objects.filter(created_on__lte=datetime.now(timezone.utc) - timedelta(hours=0, minutes=0, seconds=publisher__stats__elapsed_time_in_seconds))
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'publisher__stats__elapsed_time_in_seconds' is not defined

我可以在SQL列逻辑中使用timedelta吗? 否则我该怎么做?

根据发布者模型,如何定义要比较的字段存在问题。 您在问题中的字段是

publisher__stats__elapsed_time_in_seconds

您的查询代码是

Article.objects.filter(created_on__lte=datetime.now(timezone.utc) - timedelta(hours=0, minutes=0, seconds=publisher__stats__elapsed_time_in_seconds)).

这基本上意味着让我获得所有具有创建时间(created_on字段)早于或完全等于文章->发布者->统计记录的时间(elapsed_time_in_seconds字段)的文章。

这意味着它将在stats对象上寻找一个elapsed_time_in_seconds字段,该字段应通过FK或其他方式与您的发布者对象相关。 反过来,发布者对象需要与您的文章对象相关。

您的Article模型与Publisher模型有关,但是Publisher和Stats(??)之间似乎没有关系。 您可以检查统计模型以查看字段和关系是否正确定义吗?

根本问题是您不明白为什么会收到错误消息

name 'publisher__stats__elapsed_time_in_seconds' is not defined`.

让我们再次看一下代码:

Article.objects.filter(created_on__lte=datetime.now(timezone.utc) -
    timedelta(hours=0, minutes=0, seconds=publisher__stats__elapsed_time_in_seconds))

在上面的代码中,符号publisher__stats__elapsed_time_in_seconds被解释为变量引用,您的代码中未定义。 如果添加

publisher__stats__elapsed_time_in_seconds = 1

在上面的代码片段之前,您将不会收到错误消息。 (您也不会得到想要的结果。)您期望Django的ORM在符号publisher__stats__elapsed_time_in_seconds上运行,但是在Django可以使用之前,Python解释器必须解释代码以及编写代码的方式,这仅仅是解释器必须解析的变量名。 Django甚至没有机会看到它。

好的,防止解释器将名称解释为变量引用并让Django ORM处理名称的方法是使用F()表达式 因此,您很想这样做:

Article.objects.filter(created_on__lte=datetime.now(timezone.utc) -
    timedelta(hours=0, minutes=0, seconds=F("publisher__stats__elapsed_time_in_seconds")))

但是,然后您将不知道如何处理的参数传递给timedelta

正如schillingt评论中指出的那样, Lutz Prechelt在其他地方的答案显示了如何将F()表达式timedelta之外。 就您而言,您可以执行以下操作:

Article.objects.filter(created_on__lte=datetime.now(timezone.utc) -
        timedelta(seconds=1) * F("publisher__stats__elapsed_time_in_seconds"))))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM