Peewee ORM 查询结果 fn.COUNT 是 unicode 类型,不是整数

Peewee ORM query result fn.COUNT is type unicode, not integer

请帮助我了解 peewee 2.4.5 在与 MySQL 5.5 交谈时的行为。我是 运行 一个简单的查询,用于计算与 parent 关联的 children;在这种情况下,文档位于路径中。简单来说 SQL 归结为:

select p.name, count(d.file) as child_count 
from path as p, doc as d 
where p.id = d.path_id 
group by p.name

Peewee 代码使用 fn.COUNT 功能,请参阅下面的 self-contained 示例。结果返回得很好,结果是我期望的,但有一个例外:查询结果 object 属性 "child_count" 的类型是 unicode 而不是整数。在这个小例子中,有 1 行,我得到一个字符串(基本上)“1”而不是数字 1。

我很困惑,因为在我用 fn.COUNT 完成的其他查询中,结果是整数类型。这是一个功能吗?我在这里犯了一个愚蠢的 python 错误吗?提前致谢。

'''
Example of accessing MySQL from Python using Peewee.
Developed with peewee 2.4.5, pymysql 0.6.3, MySql 5.5
'''
from __future__ import print_function
from peewee import MySQLDatabase, Model, CharField, ForeignKeyField, fn

db = MySQLDatabase(database="test", host="localhost", user="mumble", password="foo")

class MySQLModel(Model):
    '''
    Base class to associate the database object
    '''
    class Meta:
        database = db

class Path(MySQLModel):
    # peewee adds primary key field 'id'
    name = CharField()

class Doc(MySQLModel):
    # peewee adds primary key field 'id'
    path = ForeignKeyField(Path)
    file = CharField()

def main():
    db.connect()
    db.create_tables([Path, Doc], True)
    newpath = Path(name='ab/23')
    newpath.save()
    newdoc1 = Doc(path=newpath.id, file='file1.txt')
    newdoc1.save()
    newdoc2 = Doc(path=newpath.id, file='file2.txt')
    newdoc2.save()
    for row in Path.select():
        print("Path: id=%d, name=%s" % (row.id, row.name))
    for row in Doc.select():
        print("Doc: id=%d, file=%s" % (row.id, row.file))
    # query in plain old SQL:
    # select p.name, count(d.file) from path as p, doc as d where p.id = d.path_id group by p.name
    path_doc_result = (Path
        .select(Path.name, fn.COUNT(Doc.file).alias('child_count'))
        .join(Doc, on=(Path.id == Doc.path)) 
        .group_by(Path.name))
    path_doc_count = len(list(path_doc_result))
    print("Path-doc parent-child result count is %d" % path_doc_count)
    if path_doc_count == 0:
        print("Programmer error, no results!")
    else:
        # get the first one
        d_row = path_doc_result[0]
        #### Why is the child_count attribute not integer? ###
        print("Type of child_count attribute is %s" % type(d_row.child_count))
        print("Path-Doc result: name=%s child_count=%d" % (d_row.name, int(d_row.child_count)))

    newdoc1.delete_instance()
    newdoc2.delete_instance()
    newpath.delete_instance()
    # order matters for foreign keys!
    db.drop_table(Doc)
    db.drop_table(Path)
    db.close()

if __name__ == "__main__":
    main()

Peewee 函数查看第一个参数的类型并尝试将 return 值强制转换为该类型。这在大多数情况下是有道理的,但我明白为什么它会在这里引起问题。

要变通,只需调用 fn.COUNT(Doc.file).coerce(False).alias('child_count')

path_doc_result = (Path
    .select(Path.name, fn.COUNT(Doc.file).coerce(False).alias('child_count'))
    .join(Doc, on=(Path.id == Doc.path)) 
    .group_by(Path.name))