Peewee框架fn.AVG()返回int而非预期float的问题排查
Peewee中fn.AVG()返回int而非float的原因分析
问题场景
- 使用SQLite数据库,
models.Mark.skill字段定义为IntegerField - 直接执行原生SQL查询:
得到正确浮点结果:SELECT players.name, AVG(marks.skill) FROM players JOIN marks ON player_id = players.id GROUP BY players.id;Charname | 6.6 - 但通过Peewee执行查询时:
结果被截断为int类型:from peewee import * import models query = ( models.Player.select( models.Player.name, fn.AVG(models.Mark.skill).alias('skill'), ) .join(models.Mark, JOIN.LEFT_OUTER) .group_by(models.Player.id) ) for q in query: print(q.name, q.skill, type(q.skill))Charname 6 int
核心原因
Peewee会根据被聚合字段的类型自动推断聚合结果的解析类型:
- SQLite的
AVG()函数对整数列计算时,会返回REAL(浮点)类型,这是数据库本身的特性,所以原生SQL能得到正确结果。 - 但Peewee的类型绑定逻辑中,当聚合函数作用于
IntegerField时,框架默认使用整数类型的转换器处理结果,直接将SQLite返回的浮点值强制转换为int,截断了小数部分。
解决方向
可以通过显式指定结果类型来修正:
方法1:用SQL的CAST转换结果
query = ( models.Player.select( models.Player.name, fn.CAST(fn.AVG(models.Mark.skill), 'REAL').alias('skill'), ) .join(models.Mark, JOIN.LEFT_OUTER) .group_by(models.Player.id) )
方法2:用Peewee的cast()方法指定字段类型
from peewee import FloatField query = ( models.Player.select( models.Player.name, fn.AVG(models.Mark.skill).cast(FloatField()).alias('skill'), ) .join(models.Mark, JOIN.LEFT_OUTER) .group_by(models.Player.id) )
内容的提问来源于stack exchange,提问作者Artem Ermakov
相关产品推荐
相关产品推荐

