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

16 浏览
0 Comments

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

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

我使用的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()
# 取消下一行的注释会抛出异常'TypeError: 'User' object is not iterable'
#print dict(user1)
# 这一行也会抛出'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 
    print dict(u)
TypeError: 'User' object is not iterable

0
0 Comments

在评论中提到,这是适用于现代版本SQLAlchemy的正确答案,假设"row"是一个核心行对象,而不是ORM映射的实例。

for row in resultproxy:
    row_as_dict = row._mapping  # SQLAlchemy 1.4及更高版本
    # row_as_dict = dict(row)  # SQLAlchemy 1.3及更早版本

关于`row._mapping`的背景,SQLAlchemy 1.4的新功能:https://docs.sqlalchemy.org/en/stable/core/connections.html#sqlalchemy.engine.Row._mapping

问题出现的原因是出现了"XXX对象不可迭代"的错误,我正在使用0.5.6版本,通过session.query(Klass).filter().all()获取结果。

Uniyal:请使用最小的代码片段展示出问题,并附上真实的错误回溯信息。通过评论和代码摘要很难做到这一点。

请查看更新的代码,我使用了你提到的链接中给出的相同示例,我也没有看到那里使用了dict?

请注意,这是适用于现代版本SQLAlchemy的正确答案,假设"row"是一个核心行对象,而不是ORM映射的实例。

还请注意,zzzeek是SQLAlchemy的创建者。

有人知道为什么这样做可以吗?RowProxy并没有继承自collections.Mapping, dict, collections.OrderedDict()或collections.UserDict()。而我找到的dict构造函数的描述似乎都不适用。

有人能详细解释一下吗?我是个新手,不太明白。

你说得对,它确实没有继承那些类型,但它实现了__getitem__keys等方法,因此它看起来像一个映射。 github.com/sqlalchemy/sqlalchemy/blob/…

是的,没错。 docs.python.org/3.7/glossary.html#term-mapping

核心行对象与ORM映射实例有什么区别?这对我从query(MyModel).all()的行不起作用:MyModel对象不可迭代。

我尝试过这样做,但当你有许多字段具有相同的名称时,你会得到奇怪的结果。例如,在原始查询中加入两个表,如"Select a.*, b.* from A a, B b"

这个答案不够有帮助,因为你没有说明"resultproxy"是什么或怎么使用它?

resultproxy只是一个代理变量名,代表你的结果变量。将其替换为适当的查询结果变量。

请注意,row._mapping返回的是一个RowMapping而不是一个dict。如果想要添加键或进行其他dict操作,需要将其转换为dict。

鉴于我们处于2022年,SQLAlchemy 1.4已经成熟,即将推出2.0版本,应该将此答案标记为正确答案。

Python的约定是不依赖"_anything",因为它是保留的。为什么在SQLAlchemy中这是正确的做法?

0
0 Comments

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

在这段代码中,作者遇到了一个问题,即如何将SQLAlchemy的行对象转换为Python字典。他们试图寻找一个好的答案,但没有找到一个满意的解决方案。因此,他们提供了一个自定义的函数row2dict来解决这个问题。该函数遍历行对象的每个列,并将列名作为键,将列值转换为字符串并作为值存储在字典中。

作者还添加了一行代码,以提供一个更简洁的解决方案,即使用lambda函数和字典推导式来实现相同的功能。这个一行代码的解决方案使用相同的原理,只是将代码压缩到一行中。

然后,其他人提供了一些改进的建议,例如使用return dict((col, getattr(row, col)) for col in row.__table__.columns.keys())来更简洁地实现相同的功能。

此外,有人提出了一个问题,即如果列没有分配给相同名称的属性会怎么样。在这种情况下,原始的解决方案将不起作用。为了解决这个问题,有人建议使用{c.name: getattr(self, c.name) for c in self.__table__.columns}来避免使用columns.keys()

另外还有一些评论指出了原始解决方案的一些问题,例如它无法处理使用_property定义的列,以及它返回值为字符串而不是原始类型的问题。

最后,有人提供了一个更新的解决方案{c.expression.name: getattr(obj, c.key) for c in inspect(obj).mapper.column_attrs},这个解决方案将数据库列名作为字典键,而不是使用属性名。

最新版本的SQLAlchemy允许直接使用row.columns来实现相同的功能。

为了将SQLAlchemy的行对象转换为Python字典,作者提供了一个自定义函数,并收到了其他人的改进建议和解决方案。这些解决方案使用不同的方法来实现相同的目标,并解决了一些潜在的问题。

0
0 Comments

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

在这个问题中,用户想要将SQLAlchemy的行对象转换为Python字典。他们尝试了一些方法,但是遇到了一些问题。下面是一些相关的讨论和解决方法:

- 一个用户建议使用row对象的__dict__属性来获取内部字典表示。他们给出了一个例子:for u in session.query(User).all(): print u.__dict__,但也指出这种方法会多出一个_sa_instance_state字段。

- 另一个用户解释了为什么多出的_sa_instance_state字段是一个问题,并提供了一个更好的解决方法:dictret = dict(row.__dict__); dictret.pop('_sa_instance_state', None)。这种方法在获取字典后手动删除了多余的字段。

- 有人认为这种方法不够理想,因为__dict__包含了_sa_instance_state字段,如果未来版本中添加了其他属性,可能需要手动处理它们。他们提供了另一种更简洁和错误防范的方法:{col.name: getattr(self, col.name) for col in self.__table__.columns}

- 还有其他一些用户提供了类似的解决方法,例如:{k: v for k, v in item.__dict__.iteritems() if not str(k).startswith("_")}

总之,用户试图找到一种将SQLAlchemy行对象转换为Python字典的方法。他们尝试了使用__dict__属性,但遇到了一些问题。其他用户提供了一些解决方法,包括手动删除多余字段和使用更简洁和错误防范的方法来获取字典。

0