我在这个设置中有一个疯狂的bug。django queryset从postgresql视图返回错误的值
该数据库是Postgres 9.1,并且是预先存在的(不是由Django管理)。在它存在1个表,然后一些相当简单的看法,其中一个被称为valid_logins_dow_popularity定义:
=>\d+ valid_logins_dow_popularity
View "public.valid_logins_dow_popularity"
Column | Type | Modifiers | Storage | Description
------------+------------------+-----------+---------+-------------
logins_avg | double precision | | plain |
dow | double precision | | plain |
View definition:
WITH by_dow AS (
SELECT valid_logins_over_time.count, date_part('dow'::text, valid_logins_over_time.date) AS dow
FROM valid_logins_over_time
)
SELECT avg(by_dow.count)::double precision AS logins_avg, by_dow.dow
FROM by_dow
GROUP BY by_dow.dow
ORDER BY by_dow.dow;
在Django的1.4,我定义使用该视图一个简单的模型,因为它的数据源:
class ValidLoginsDowPopularity(models.Model):
class Meta:
db_table = 'valid_logins_dow_popularity'
managed = False
logins_avg = models.FloatField(
db_column='logins_avg')
# Day of Week (dow)
dow = models.IntegerField(db_column='dow',
primary_key=True)
def __unicode__(self):
return u"%d : " % (self.dow, self.logins_avg)
当我直接从数据库中获取数据,我得到一组数字:
SELECT "valid_logins_dow_popularity"."logins_avg", "valid_logins_dow_popularity"."dow"
FROM "valid_logins_dow_popularity";
logins_avg | dow
------------------+-----
28.8571428571429 | 0
95.1428571428571 | 1
91.4285714285714 | 2
89.625 | 3
82.6666666666667 | 4
61.4285714285714 | 5
28.4285714285714 | 6
(7 rows)
当我得到的DAT一个通过Django的模型我得到一个有点含糊相关,但不同组数字:
In [1]: from core.models import *
In [2]: v = ValidLoginsDowPopularity.objects.all()
In [3]: for i in v:
print "logins_avg : %f | dow : %d" % (i.logins_avg, i.dow)
...:
logins_avg : 25.857143 | dow : 0
logins_avg : 85.571429 | dow : 1
logins_avg : 89.571429 | dow : 2
logins_avg : 86.375000 | dow : 3
logins_avg : 83.000000 | dow : 4
logins_avg : 67.000000 | dow : 5
logins_avg : 28.000000 | dow : 6
到今天为止,我已经验证了Django的产生,当在psql直接运行返回预期输出的SQL。我同样尝试使用一个IntegerField,FloatField和DecimalField作为login_avg属性的Django模型 - 都具有相同的但不正确的值。我也写了一个简单的测试程序来绕过Django的代码并确保它不是一个psycopg2问题:
import psycopg2
def main():
conn_string = "dbname='********' user='*********'"
conn = psycopg2.connect(conn_string)
cursor = conn.cursor()
sql = "select * from valid_logins_dow_popularity"
cursor.execute(sql)
for rec in cursor.fetchall():
print rec
if __name__ == '__main__':
main()
,当运行给出正确的过错,所以psycopg2似乎是在做正确的事:
$ python test_psycopg2.py
(28.8571428571429, 0.0)
(95.1428571428571, 1.0)
(91.4285714285714, 2.0)
(89.625, 3.0)
(82.6666666666667, 4.0)
(61.4285714285714, 5.0)
(28.4285714285714, 6.0)
这怎么可能?任何线索将不胜感激。我可以在哪里挖掘Django代码并查看出现问题的地方?我应该用Django项目报告这个问题吗?
视图/表中的logins_avg字段的数据库类型是什么?我怀疑从那转换到FloatField类型不能正常工作。 – 2012-08-02 17:08:50
好主意。我已经编辑了这个问题以获得这些细节,但我也尝试将login_avg列转换为int,将模型更新为IntegerField,但仍然存在奇数值差异。 – portman 2012-08-02 17:27:35
FloatField应正确映射到“双精度”...您使用的是什么python数据库引擎? postgresql_psycopg2?你也可以尝试DecimalField而不是FloatField,看看是否改变了任何东西 – 2012-08-02 18:49:17