如何将SQLAlchemy行对象转换为Python字典?

432 投票
46 回答
540049 浏览
提问于 2025-04-15 17:20

有没有简单的方法可以遍历列名和对应的值呢?

我使用的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

46 个回答

244

根据@zzzeek在评论中的说法:

请注意,这个答案适用于现代版本的SQLAlchemy,前提是“row”是一个核心行对象,而不是一个ORM映射的实例。

for row in resultproxy:
    row_as_dict = row._mapping  # SQLAlchemy 1.4 and greater
    # row_as_dict = dict(row)  # SQLAlchemy 1.3 and earlier

关于row._mapping的背景信息,这是在SQLAlchemy 1.4中新增的功能:https://docs.sqlalchemy.org/en/stable/core/connections.html#sqlalchemy.engine.Row._mapping

386

你可以访问一个SQLAlchemy对象的内部__dict__,方法如下:

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

我没有找到一个好的答案,所以我用了这个:

def row2dict(row):
    d = {}
    for column in row.__table__.columns:
        d[column.name] = str(getattr(row, column.name))

    return d

补充:如果上面的函数太长,不太符合某些人的口味,这里有一个一行代码的写法(适用于Python 2.7及以上版本)

row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns}

撰写回答