簡體   English   中英

Django 按時間過濾日期時間字段,不考慮日期

[英]Django filter datetime field by time, irrespective of date

我在 Django 中有一個日期時間字段,我想根據時間過濾它。 我不關心特定日期,但我想查找 7:30 之前的所有交易,例如。

我知道我可以按小時和分鍾過濾,例如:

Q(datetime__hour=7) & \
Q(datetime__minute=30)

但是,這會在 7:30 找到所有交易。 您也無法申請 gte 或 lte。 IE

(Q(datetime__hour__lte=7) & \
Q(datetime__minute__lte=30)) | \
Q(datetime__hour__lt=7)

唯一似乎是潛在解決方案的是有許多查詢,例如:

(Q(datetime__hour=7) & \
(Q(datetime__minute=30) | \
 Q(datetime__minute=29) | \
 Q(datetime__minute=28) | \
 ....
 Q(datetime__minute=2) | \
 Q(datetime__minute=1) | \
 Q(datetime__minute=0))) | \
Q(datetime__hour=6) | \
Q(datetime__hour=5) | \
Q(datetime__hour=4) | \
Q(datetime__hour=3) | \
Q(datetime__hour=2) | \
Q(datetime__hour=1) | \
Q(datetime__hour=0)

但這似乎很荒謬。

有人有主意嗎?

只需將日期時間字段拆分為日期和時間字段即可。 比你只能按時過濾:

from datetime import combine

class MyModel(models.Model):
    start_date = models.DateField()
    start_time = models.TimeField()

    class Meta:
        ordering = ['start_date', 'start_time']

    def start_datetime(self):
        return combine(self.date, self.time)

我添加了 Meta.ordering 和 start_datetime model 方法來表明這個 model 可以像帶有 DateTimeField 的 model 一樣呈現數據。

現在您可以按時過濾:

objects = MyModel.objects.filter(start_time__lt=time(7, 30))

更新

如果您有一個已建立的項目並且許多查詢都依賴於具有正常的 DateTime 字段。 將日期時間拆分為日期和時間字段是有代價的:重寫查詢會使您的項目失敗。 有一個替代方案:只添加一個時間字段並保持日期時間字段不變。 保存方法可以根據日期時間添加時間。 不利的一面是您的數據庫中有重復的數據。 好處是它可以以最小的努力解決您的問題。

class MyModel(models.Model):
    start_datetime = models.DateTimeField()
    start_time = models.TimeField(blank=True)

    def save(self)
        self.start_time = self.start_datetime.time

所有現有查詢都將與以前相同,並且僅按時間過濾:

objects = MyModel.objects.filter(start_time__lt=time(7, 30))

在 Django 1.7+ 中,您可以使用轉換從時間戳中提取分鍾和小時。 有關詳細信息,請參閱https://docs.djangoproject.com/en/1.7/howto/custom-lookups/#a-simple-transformer-example

不確定何時引入按時間篩選,但在 Django (4.0+) 的最新版本中,這是通過以下查詢語法完成的:

YourModel.objects.all().filter(datetime__hour__lte=7, datetime__minute__lte=30)

其中YourModel是您要過濾的 model, datetime是來自該 model 的字段。

想法:

  • 使用原始 sql
  • (mem) 緩存你的結果 (eq::pseudocode:: md5(sql_string) = sql_result)。
  • 創建一個包含 5 個索引 integer 列(年、月、日、小時、分鍾)的中間表。 在您主要的 sql 提取之前檢查此表以獲取所需的數據(查詢應該非常快)。 如果什么都不存在,請進行“神奇”交易(最好不要使用 Django 的 ORM)。 結果將其用於您的目的,但也將其復制到您的輔助表中。
  • 當你厭倦了做不必要的操作時,減少一些睡眠時間並根據項目需求優化你的 sql 結構:需要什么數據,數據庫寫入量與數據庫讀取量,內部/外部連接等等......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM