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