使用Django ORM过滤日期时间范围时出现奇怪的行为

时间:2013-01-01 21:04:22

标签: python django orm sqlite

我正在尝试使用Django从sqlite数据库查询数据。

模型

class SolarEntryHour(models.Model):
    time = models.DateTimeField()
    device = models.ForeignKey(Device)
    lW = models.DecimalField(max_digits=9, decimal_places=3)

    class Meta:
        unique_together = (("time", "device"))

我如何尝试访问数据

start = datetime.datetime.utcnow()+relativedelta(hour=0, minute=0, second=0, microsecond=0)
end = datetime.datetime.utcnow()

ticks = SolarEntryHour.objects.filter(
    time__range=(start, end), 
    device = str(deviceID)
)

发生了什么

Exception Value:    
list index out of range
Exception Location: /usr/lib/python2.7/dist-packages/django/db/backends/util.py in typecast_timestamp, line 97

当查询实际执行时(在迭代“ticks”时)似乎发生异常 查询Django尝试执行,print start; print end的输出看起来很好

2013-01-01 00:00:00 - 2013-01-01 20:47:24.245942

SELECT "charts_solarentryhour"."id", "charts_solarentryhour"."time", "charts_solarentryhour"."device_id", "charts_solarentryhour"."lW" 
FROM "charts_solarentryhour" 
WHERE ("charts_solarentryhour"."device_id" = 1  AND "charts_solarentryhour"."time" 
BETWEEN 2013-01-01 00:00:00 and 2013-01-01 20:47:24.245942)

修改
我想我找到了问题,但我不知道这是预期的行为还是Django Bug。

表“charts_solarentryhour”的“time”字段定义为:
time = models.DateTimeField()
此表由数据库触发器填充,而不是输入此字段的完整日期时间,soley strftime('%Y-%m-%d %H', 'now')

当Django然后执行查询时,它在解析查询结果时失败,因为从数据库返回的字符串中没有分钟和秒数(这就是为什么列表索引超出范围异常的原因)

不填充整个日期时间字段是不好的做法? Django不应该添加一些零吗? 有没有很好的方法来解决这个问题而不回退原始查询执行?

2 个答案:

答案 0 :(得分:0)

问:不填充整个日期时间字段是不好的做法吗?

是的 - 有很多工具可以很好地解析格式良好的标准日期格式。因此,当您发明自己的格式时,期望发生不好的事情。 Django和几乎所有框架都希望您使用标准字段类型的既定约定。

问:Django不应该添加一些零吗?

不 - 这将是黑魔法。 “2013-01-10 10”没有传统意义。

问:有没有什么好办法可以解决这个问题而不回退原始查询执行?

是 - 请在此处查看答案:Format for DateTimeField

答案 1 :(得分:0)

这不是Django的问题 是dateutil的relativedelta函数的奇怪行为

你必须写下以下内容:

  
    
      

start = datetime.datetime.utcnow()+ relativedelta(小时= 0,分钟= 0,秒= 0,微秒= 0)

    
  

而不是

  

start = datetime.datetime.utcnow()+ relativedelta(小时= 0,分钟= 0,秒= 0,微秒= 0)

小时更改替换(并且不添加)初始值

>>>import datetime
>>>from dateutil.relativedelta import relativedelta
>>>t1 = datetime.datetime.utcnow()
>>>t1 
datetime.datetime(2013, 11, 20, 18, 55, 11, 895897)
>>>t2 = t1 + relativedelta(hour=1, minute=3, second=7, microsecond=1) 
>>>t2
datetime.datetime(2013, 11, 20, 1, 3, 7, 1)
>>>t3 = t1 + relativedelta(hours=1, minutes=1, seconds=1, microseconds=1) 
>>>t3
datetime.datetime(2013, 11, 20, 19, 56, 12, 895898)