Sqlalchemy获取结果为KeyedTuple而非映射对象

4 投票
1 回答
3052 浏览
提问于 2025-04-18 04:22

假设你有一个简单的SQLAlchemy映射对象,像这样:

class User(Base):
    __tablename__ = 'users'
    id = sqlalchemy.Column(sqlalchemy.Integer, autoincrement=True,primary_key=True)
    name = sqlalchemy.Column(sqlalchemy.Unicode(255), unique=True, nullable=False)
    email = sqlalchemy.Column(sqlalchemy.Unicode(255), nullable=False)
    address = sqlalchemy.Column(sqlalchemy.Unicode(255), nullable=False)

用户是这样创建的:

sess.add(User(name=u'One', email=u'one@example.com', address='An address'))
sess.add(User(name=u'Two', email=u'two@example.com', address='An address'))
sess.add(User(name=u'Three', email=u'three@example.com', address='An address'))

然后你可以用以下方式查询这三个用户:

1.)

sess.query(User).all()
[<__main__.User object at 0x2fb9790>, <__main__.User object at 0x2fb9810>, <__main__.User object at 0x2fb9890>]

这会给你一个用户对象的列表。

2.)

sess.query(User.id, User.name, User.email, User.address).all()
[(1, u'one@example.com', u'An address'), (2, u'two@example.com', u'An address'), (3, u'three@example.com', u'An address')]

这会给你一个KeyedTuple对象的列表,你可以通过属性名来引用字段,比如 sess.query(User.id, User.name, User.email, User.address).all()[0].name。

3.)

sess.execute(sess.query(User)).fetchall()
[(1, u'One', u'one@example.com', u'An address'), (2, u'Two', u'two@example.com', u'An address'), (3, u'Three', u'three@example.com', u'An address')]

这会给你一个RowProxy对象的列表,你可以像这样引用字段:sess.execute(sess.query(User)).fetchall()[0]['users_name']。

我想问的是,有没有简单的方法可以得到第二个查询的结果,而不需要列出用户类的所有属性,或者有没有办法用像'name'这样的键来获取第三个查询的结果,而不是'users_name',这样就能和用户类中的属性名一致。

所以基本上我需要的是一个包含用户类所有列属性的对象,并且这些属性可以像res.name或res['name']这样引用。

这样我只需要属性,而不需要整个用户对象和其他的东西。

这样遍历属性会很简单,因为你可以直接用res.keys()。

我希望我的问题很清楚。

我知道这和用户实例非常相似,但还是不完全一样。

我希望的解决方案是得到一个KeyedTuple作为结果,而不需要明确列出属性。

提前谢谢你。

1 个回答

5

我不太确定你的目标是什么,但你是不是想处理动态的列数据呢?可能还有其他方法,但你可以像这样把表格的列作为查询参数来解包:

>>> user_columns = User.__table__.columns
>>> sess.query(*user_columns).all()  # unpack user_columns into arguments
[(1, u'One', u'one@example.com', u'An address'), (2, u'Two', u'two@example.com', u'An address'), (3, u'Three', u'three@example.com', u'An address')]

撰写回答