我是Python和Pyramid的新手。在我用来了解更多关于Pyramid的测试应用程序中,我想查询数据库并根据sqlalchemy查询对象的结果创建一个字典,最后将字典发送到变色龙模板。
到目前为止,我有以下代码(工作正常),但我想知道是否有更好的方法来创建我的字典。
...
index = 0
clients = {}
q = self.request.params['q']
for client in DBSession.query(Client).filter(Client.name.like('%%%s%%' % q)).all():
clients[index] = { "id": client.id, "name": client.name }
index += 1
output = { "clients": clients }
return output
在学习Python的过程中,我发现了一种在for循环语句中创建列表的好方法,如下所示:
myvar = [user.name for user in users]
那么,我遇到的另一个问题是:是否有与上述类似的“一行”方式来创建sqlalchemy查询对象的字典?
提前致谢。
答案 0 :(得分:7)
首先,这种模式:
index = 0
for item in seq:
frobnicate(index, item)
item += 1
很常见,有一个内置函数自动执行enumerate()
,就像这样使用:
for index, item in enumerate(seq):
frobnicate(index, item)
但是,我不确定你是否需要它,将事物与从零开始的整数索引相关联是一个列表的功能,你真的不需要一个字典;除非你想要漏洞,或者需要一些dicts的其他特殊功能,否则就这样做:
stuff = []
stuff.extend(seq)
当你只对数据库实体的一小部分属性感兴趣时,最好告诉sqlalchemy发出只返回的查询:
query = DBSession.query(Client.id, Client.name) \
.filter(q in Client.name)
在上面我还将.name.like('%%%s%%' % q)
简化为q in name
因为它们的意思相同(sqlalchemy将它扩展为正确的LIKE
表达式)
以这种方式构造的查询返回一个看起来像元组的special thing,并且可以通过调用它上面的_asdict()
轻松地变成一个字典:
所以要把它们放在一起
output = [row._asdict() for row in DBSession.query(Client.id, Client.name)
.filter(q in Client.name)]
或者,如果你真的迫切需要它成为一个词典,你可以使用词典理解:
output = {index: row._asdict()
for index, row
in enumerate(DBSession.query(Client.id, Client.name)
.filter(q in Client.name))}
答案 1 :(得分:3)
@TokenMacGuy为您的问题提供了一个很好的详细解答。但是,我觉得你提出了一个错误的问题:)
在将SQLALchemy对象传递给模板之前,您不需要将它们转换为字典 - 这将非常不方便。您可以按原样传递查询结果,并直接在模板中使用SQLALchemy映射对象
q = self.request.params['q']
clients = DBSession.query(Client).filter(q in Client.name).all()
return {'clients': clients}
答案 2 :(得分:0)
如果要将SqlAlchemy对象转换为dict,可以使用以下代码:
def obj_to_dict(obj):
return dict((col.name, getattr(obj, col.name)) for col in sqlalchemy_orm.class_mapper(obj.__class__).mapped_table.c)
映射表的另一个属性中包含关系,但代码有点冒险。
您不需要将对象转换为任何模板库的dict,但如果您决定保留数据(memcached,session,pickle等),您将需要使用dicts或写一些代码将持久化数据“合并”回会话。
快速注意事项 - 如果您通过json渲染任何此类数据,您将需要具有可以处理日期时间对象的自定义json渲染器,或更改函数中的值。