簡體   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