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。即
(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 模型方法,以表明该模型可以像具有 DateTimeField 的模型一样呈现数据。
现在您可以按时间过滤:
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 了解详情。
想法:
- 使用原始 sql
- (mem)缓存你的结果 (e.q.::pseudocode:: md5(sql_string) = sql_result).
- 创建一个具有 5 个索引整数列(年、月、日、小时、分钟)的中间 table。在您的主要 sql 提取之前检查此 table 以获取所需的数据(查询应该非常快)。如果什么都不存在,请进行 "magic" 事务(最好不要使用 Django 的 ORM)。结果将其用于您的目的,但也将其复制到您的辅助 table.
- 当您厌倦了执行不必要的操作时,可以减少一些睡眠时间并根据项目需求优化您的 sql 结构:需要什么数据、数据库写入量与数据库读取量、inner/outer 加入等等...
我在 Django 中有一个日期时间字段,我想根据时间过滤它。我不关心特定日期,但我想查找 7:30 之前的所有交易,例如。
我知道我可以按小时和分钟过滤,例如:
Q(datetime__hour=7) & \
Q(datetime__minute=30)
但是,这会找到所有在 7:30 处的交易。您也无法申请 gte 或 lte。即
(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 模型方法,以表明该模型可以像具有 DateTimeField 的模型一样呈现数据。
现在您可以按时间过滤:
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 了解详情。
想法:
- 使用原始 sql
- (mem)缓存你的结果 (e.q.::pseudocode:: md5(sql_string) = sql_result).
- 创建一个具有 5 个索引整数列(年、月、日、小时、分钟)的中间 table。在您的主要 sql 提取之前检查此 table 以获取所需的数据(查询应该非常快)。如果什么都不存在,请进行 "magic" 事务(最好不要使用 Django 的 ORM)。结果将其用于您的目的,但也将其复制到您的辅助 table.
- 当您厌倦了执行不必要的操作时,可以减少一些睡眠时间并根据项目需求优化您的 sql 结构:需要什么数据、数据库写入量与数据库读取量、inner/outer 加入等等...