简体   繁体   English

在金字塔中创建sqlalchemy查询对象的字典

[英]Create dictionary of a sqlalchemy query object in Pyramid

I am new to Python and Pyramid. 我是Python和Pyramid的新手。 In a test application I am using to learn more about Pyramid, I want to query a database and create a dictionary based on the results of a sqlalchemy query object and finally send the dictionary to the chameleon template. 在一个测试应用程序中,我将用来了解有关Pyramid的更多信息,我想查询一个数据库并根据sqlalchemy查询对象的结果创建一个字典,最后将字典发送给chameleon模板。

So far I have the following code (which works fine), but I wanted to know if there is a better way to create my dictionary. 到目前为止,我有以下代码(工作正常),但是我想知道是否有更好的方法来创建字典。

...
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

While learning Python, I found a nice way to create a list in a for loop statement like the following: 在学习Python时,我发现了一种在for循环语句中创建列表的好方法,如下所示:

myvar = [user.name for user in users]

So, the other question I had: is there a similar 'one line' way like the above to create a dictionary of a sqlalchemy query object? 因此,我还有另一个问题:是否有类似上述的“一行”方法来创建sqlalchemy查询对象的字典?

Thanks in advance. 提前致谢。

well, yes, we can tighten this up a bit. 好吧,是的,我们可以收紧它。

First, this pattern: 首先,这种模式:

 index = 0
 for item in seq:
     frobnicate(index, item)
     item += 1

is common enough that there's a builtin function that does it automatically, enumerate() , used like this: 很常见,有一个内置函数可以自动执行该功能,即enumerate() ,其用法如下:

 for index, item in enumerate(seq):
     frobnicate(index, item)

but , I'm not sure you need it, Associating things with an integer index starting from zero is the functionality of a list, you don't really need a dict for that; 但是 ,我不确定您是否需要它,将事物与从零开始的整数索引相关联是列表的功能,您实际上并不需要一个字典。 unless you want to have holes, or need some of the other special features of dicts, just do: 除非您希望有漏洞或需要dict的其他一些特殊功能,否则请执行以下操作:

 stuff = []
 stuff.extend(seq)

when you're only interested in a small subset of the attributes of a database entity, it's a good idea to tell sqlalchemy to emit a query that returns only that: 当您只对数据库实体的一小部分属性感兴趣时,最好告诉sqlalchemy发出仅返回以下内容的查询:

 query = DBSession.query(Client.id, Client.name) \
                  .filter(q in Client.name)

In the above i've also shortened the .name.like('%%%s%%' % q) into just q in name since they mean the same thing (sqlalchemy expands it into the correct LIKE expression for you) 在上面我也将.name.like('%%%s%%' % q)缩写为q in name因为它们表示同一意思(sqlalchemy将其扩展为适合您的正确LIKE表达式)

Queries constructed in this way return a special thing that looks like a tuple, and can be easily turned into a dict by calling _asdict() on it: 以这种方式构造的查询返回一个特殊的东西 ,看起来像一个元组,并且可以通过在其上调用_asdict()轻松地将其变成dict:

so to put it all together 所以放在一起

output = [row._asdict() for row in DBSession.query(Client.id, Client.name)
                                            .filter(q in Client.name)]

or, if you really desperately need it to be a dict, you can use a dict comprehension: 或者,如果您真的非常需要它作为字典,则可以使用字典理解:

output = {index: row._asdict() 
          for index, row 
          in enumerate(DBSession.query(Client.id, Client.name)
                                .filter(q in Client.name))}

@TokenMacGuy gave a nice and detailed answer to your question. @TokenMacGuy为您的问题提供了一个很好而详尽的答案。 However, I have a feeling you've asked a wrong question :) 但是,我有一种感觉,你问错了问题:)

You don't need to convert SQLALchemy objects to dictionaries before passing them to the template - that would be quite inconvenient. 在将SQLALchemy对象传递到模板之前,无需将它们转换为字典-这样做非常不便。 You can pass the result of a query as is and directly use SQLALchemy mapped objects in your template 您可以按原样传递查询结果,并直接在模板中使用SQLALchemy映射的对象

q = self.request.params['q']
clients = DBSession.query(Client).filter(q in Client.name).all()
return {'clients': clients}

If you want to turn a SqlAlchemy object into a dict, you can use this code: 如果要将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)

there is another attribute of the mapped table that has the relationships in it , but the code gets dicey. 映射表的另一个属性中具有关系,但是代码变得简单。

you don't need to cast an object into a dict for any of the template libraries, but if you decide to persist the data ( memcached, session, pickle, etc ) you'll either need to use dicts or write some code to 'merge' the persisted data back into the session. 您无需将任何模板库的对象强制转换为字典,但是如果您决定保留数据(内存缓存,会话,泡菜等),则需要使用字典或将一些代码写入“将持久数据合并回会话。

a quick side note- if you render any of this data through json , you'll either need to have a custom json renderer that can handle datetime objects , or change the values in a function. 简要说明一下-如果您通过json渲染任何这些数据,则需要拥有一个可以处理datetime对象的自定义json渲染器,或者更改函数中的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM