[英]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.