是否有一种简单的方法来遍历列名和值对?

我的SQLAlchemy版本是0.5.6

下面是我尝试使用dict(row)的示例代码:

import sqlalchemy
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

print "sqlalchemy version:",sqlalchemy.__version__ 

engine = create_engine('sqlite:///:memory:', echo=False)
metadata = MetaData()
users_table = Table('users', metadata,
     Column('id', Integer, primary_key=True),
     Column('name', String),
)
metadata.create_all(engine) 

class User(declarative_base()):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True)
    name = Column(String)
    
    def __init__(self, name):
        self.name = name

Session = sessionmaker(bind=engine)
session = Session()

user1 = User("anurag")
session.add(user1)
session.commit()

# uncommenting next line throws exception 'TypeError: 'User' object is not iterable'
#print dict(user1)
# this one also throws 'TypeError: 'User' object is not iterable'
for u in session.query(User).all():
    print dict(u)

在我的系统输出上运行这段代码:

Traceback (most recent call last):
  File "untitled-1.py", line 37, in <module>
    print dict(u)
TypeError: 'User' object is not iterable

当前回答

一个非常简单的解决方案:row._asdict()。

sqlalchemy引擎。Row _asdict () (v1。4)。 sqlalchemy KeyedTuple util。_asdict (3) (v1。)

> data = session.query(Table).all()
> [row._asdict() for row in data]

其他回答

正在迭代的表达式求值为模型对象列表,而不是行。下面是正确的用法:

for u in session.query(User).all():
    print u.id, u.name

你真的需要把它们转换成字典吗?当然,有很多方法,但是你不需要SQLAlchemy的ORM部分:

result = session.execute(User.__table__.select())
for row in result:
    print dict(row)

更新:看一下sqlalchemy.orm.attributes模块。它有一组处理对象状态的函数,这可能对您很有用,特别是instance_dict()。

在@balki回答之后,从SQLAlchemy 0.8开始,您可以使用_asdict(),可用于KeyedTuple对象。这为最初的问题提供了一个非常直接的答案。只是,在你的例子中改变最后两行(for循环):

for u in session.query(User).all():
   print u._asdict()

这是因为在上面的代码中u是类型类KeyedTuple的对象,因为.all()返回KeyedTuple的列表。因此,它有_asdict()方法,该方法很好地将u作为字典返回。

WRT @STB: AFAIK的答案,任何。all()返回的是一个KeypedTuple的列表。因此,无论是否指定列,只要处理的是应用于Query对象的.all()的结果,上述方法都是有效的。

有了这段代码,您还可以添加到您的查询“过滤器”或“连接”,这工作!

query = session.query(User)
def query_to_dict(query):
        def _create_dict(r):
            return {c.get('name'): getattr(r, c.get('name')) for c in query.column_descriptions}

    return [_create_dict(r) for r in query]

你在你的项目中到处都需要它,我很欣赏@anurag的回答,它很好。直到这一点上,我正在使用它,但它会混乱你所有的代码,也不会与实体改变工作。

不如试试这个, 继承SQLAlchemy中的基查询类

from flask_sqlalchemy import SQLAlchemy, BaseQuery


class Query(BaseQuery):
    def as_dict(self):
        context = self._compile_context()
        context.statement.use_labels = False
        columns = [column.name for column in context.statement.columns]

        return list(map(lambda row: dict(zip(columns, row)), self.all()))


db = SQLAlchemy(query_class=Query)

在那之后,无论你在哪里定义你的对象“as_dict”方法都会在那里。

Anurag Uniyal版本的改进版本,考虑了类型:

def sa_vars(row):
    return {
        column.name: column.type.python_type(getattr(row, column.name))
        for column in row.__table__.columns
    }