简体   繁体   English

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

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

I'm using Django and Python 3.7. 我正在使用Django和Python 3.7。 I have the below two models ... 我有以下两种型号...

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

I want to write a Django ORM query where given a publisher and an elapsed time in seconds (a WebPageStat record), I find all articles whose "created_on" date is not older than the elapsed time in seconds. 我想编写一个Django ORM查询,其中给定发布者和经过的时间(以秒为单位)(WebPageStat记录),我发现所有“ created_on”日期不早于经过的时间(以秒为单位)的文章。 Many have suggested using "timedelta," in other posts, but that doesn't seem to be working for me here ... 许多人建议在其他帖子中使用“ 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

Can I use timedelta with SQL column logic? 我可以在SQL列逻辑中使用timedelta吗? Otherwise how do I do this? 否则我该怎么做?

Based on your publisher model, there is a problem on how you are defining the field to compare with. 根据发布者模型,如何定义要比较的字段存在问题。 Your field in the question is 您在问题中的字段是

publisher__stats__elapsed_time_in_seconds

Your query code is 您的查询代码是

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

This basically means get me all articles that have a creation time(created_on field) before or exactly equal to the time(elapsed_time_in_seconds field) for the article-->publisher-->stats record. 这基本上意味着让我获得所有具有创建时间(created_on字段)早于或完全等于文章->发布者->统计记录的时间(elapsed_time_in_seconds字段)的文章。

This means it looks for a elapsed_time_in_seconds field on the stats object which should be related to your publisher object via a FK or some other way. 这意味着它将在stats对象上寻找一个elapsed_time_in_seconds字段,该字段应通过FK或其他方式与您的发布者对象相关。 The publisher object in turn needs to be related to your article object. 反过来,发布者对象需要与您的文章对象相关。

Your Article model is related to the Publisher model, but there does not seem to be a relation between the Publisher and the Stats (??). 您的Article模型与Publisher模型有关,但是Publisher和Stats(??)之间似乎没有关系。 Can you check the stats model to see that the field and the relation is defined correctly? 您可以检查统计模型以查看字段和关系是否正确定义吗?

The root problem here is that you don't understand why you are getting the error 根本问题是您不明白为什么会收到错误消息

name 'publisher__stats__elapsed_time_in_seconds' is not defined`.

Let's look at the code again: 让我们再次看一下代码:

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

In the code above the symbol publisher__stats__elapsed_time_in_seconds is interpreted as a variable reference, which is not defined in your code. 在上面的代码中,符号publisher__stats__elapsed_time_in_seconds被解释为变量引用,您的代码中未定义。 If you added 如果添加

publisher__stats__elapsed_time_in_seconds = 1

just before the code snippet above, then you would not get the error. 在上面的代码片段之前,您将不会收到错误消息。 (You would also not get the results you want.) You're expecting Django's ORM to operate on the symbol publisher__stats__elapsed_time_in_seconds but before Django can get to it, the Python interpreter must interpret the code, and the way the code is written, that's just a variable name which the interpreter must resolve. (您也不会得到想要的结果。)您期望Django的ORM在符号publisher__stats__elapsed_time_in_seconds上运行,但是在Django可以使用之前,Python解释器必须解释代码以及编写代码的方式,这仅仅是解释器必须解析的变量名。 Django does not get a chance to even see it. Django甚至没有机会看到它。

Ok so the way to prevent the interpreter to interpret the name as a variable reference, and have Django ORM's process the name, is to use F() expressions . 好的,防止解释器将名称解释为变量引用并让Django ORM处理名称的方法是使用F()表达式 So you'd be tempted to just do this: 因此,您很想这样做:

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

But then you'd be passing to timedelta a parameter it does not know how to handle. 但是,然后您将不知道如何处理的参数传递给timedelta

As schillingt pointed out in a comment , an answer elsewhere by Lutz Prechelt shows how to move the F() expression outside the timedelta . 正如schillingt评论中指出的那样, Lutz Prechelt在其他地方的答案显示了如何将F()表达式timedelta之外。 In your case, you could do this: 就您而言,您可以执行以下操作:

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