Anu*_*yal 220 python sqlalchemy
是否有一种简单的方法来迭代列名和值对?
我的sqlalchemy版本是0.5.6
下面是我尝试使用dict(row)的示例代码,但它抛出异常,TypeError:'User'对象不可迭代
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)
Run Code Online (Sandbox Code Playgroud)
在我的系统输出上运行此代码:
sqlalchemy version: 0.5.6
Traceback (most recent call last):
File "untitled-1.py", line 37, in <module>
print dict(u)
TypeError: 'User' object is not iterable
Run Code Online (Sandbox Code Playgroud)
hll*_*lau 216
您可以访问__dict__
SQLAlchemy对象的内部,如下所示::
for u in session.query(User).all():
print u.__dict__
Run Code Online (Sandbox Code Playgroud)
Anu*_*yal 137
我无法得到一个好的答案所以我用这个:
def row2dict(row):
d = {}
for column in row.__table__.columns:
d[column.name] = str(getattr(row, column.name))
return d
Run Code Online (Sandbox Code Playgroud)
编辑:如果上面的功能太长而且不适合某些口味这里是一个单线程(python 2.7+)
row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns}
Run Code Online (Sandbox Code Playgroud)
Ale*_*vik 75
for row in resultproxy:
row_as_dict = dict(row)
Run Code Online (Sandbox Code Playgroud)
Raz*_*erM 71
在SQLAlchemy v0.8及更高版本中,使用检查系统.
from sqlalchemy import inspect
def object_as_dict(obj):
return {c.key: getattr(obj, c.key)
for c in inspect(obj).mapper.column_attrs}
user = session.query(User).first()
d = object_as_dict(user)
Run Code Online (Sandbox Code Playgroud)
请注意,这.key
是属性名称,可以与列名称不同,例如在以下情况中:
class_ = Column('class', Text)
Run Code Online (Sandbox Code Playgroud)
这种方法也适用column_property
.
bal*_*lki 36
行有一个_asdict()
函数,给出一个字典
In [8]: r1 = db.session.query(Topic.name).first()
In [9]: r1
Out[9]: (u'blah')
In [10]: r1.name
Out[10]: u'blah'
In [11]: r1._asdict()
Out[11]: {'name': u'blah'}
Run Code Online (Sandbox Code Playgroud)
sla*_*nic 20
使用 sqlalchemy 1.4
session.execute(select(User.id, User.username)).mappings().all()
>> [{'id': 1, 'username': 'Bob'}, {'id': 2, 'username': 'Alice'}]
Run Code Online (Sandbox Code Playgroud)
Sam*_*rne 17
正如@balki所说:
_asdict()
如果您要查询特定字段,则可以使用该方法,因为它是作为KeyedTuple返回的.
In [1]: foo = db.session.query(Topic.name).first()
In [2]: foo._asdict()
Out[2]: {'name': u'blah'}
Run Code Online (Sandbox Code Playgroud)
然而,如果您没有指定列,则可以使用其他建议方法之一 - 例如@charlax提供的方法.请注意,此方法仅适用于2.7+.
In [1]: foo = db.session.query(Topic).first()
In [2]: {x.name: getattr(foo, x.name) for x in foo.__table__.columns}
Out[2]: {'name': u'blah'}
Run Code Online (Sandbox Code Playgroud)
小智 15
老问题,但由于这是谷歌"sqlalchemy row to dict"的第一个结果,值得一个更好的答案.
SqlAlchemy返回的RowProxy对象具有items()方法:http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items
它只返回一个(键,值)元组列表.所以可以使用以下代码将行转换为dict:
在Python <= 2.6中:
rows = conn.execute(query)
list_of_dicts = [dict((key, value) for key, value in row.items()) for row in rows]
Run Code Online (Sandbox Code Playgroud)
在Python> = 2.7中:
rows = conn.execute(query)
list_of_dicts = [{key: value for (key, value) in row.items()} for row in rows]
Run Code Online (Sandbox Code Playgroud)
Mar*_*ani 12
from sqlalchemy.orm import class_mapper
def asdict(obj):
return dict((col.name, getattr(obj, col.name))
for col in class_mapper(obj.__class__).mapped_table.c)
Run Code Online (Sandbox Code Playgroud)
jgb*_*rah 11
在@balki回答之后,从SQLAlchemy 0.8开始,您可以使用_asdict(),可用于KeyedTuple对象.这为原始问题提供了一个非常简单的答案.只是,在你的例子中改变这一行的最后两行(for循环):
for u in session.query(User).all():
print u._asdict()
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为在上面的代码中,u是类KeyedTuple类型的对象,因为.all()返回KeyedTuple的列表.因此它有_asdict()方法,它很好地将你作为字典返回.
WRST答案:@STB:AFAIK,anithong .all()返回的是KeypedTuple的列表.因此,只要您正在处理应用于Query对象的.all()的结果,如果您指定了一个列,上述方法就会起作用.
F.R*_*aab 11
假设将以下函数添加到以下函数中将class User
返回所有列的所有键值对:
def columns_to_dict(self):
dict_ = {}
for key in self.__mapper__.c.keys():
dict_[key] = getattr(self, key)
return dict_
Run Code Online (Sandbox Code Playgroud)
与其他答案不同,只返回对象的那些属性,这些属性是对象Column
类级别的属性.因此,不包括SQLalchemy或您添加到对象的_sa_instance_state
任何其他属性.参考
编辑:忘了说,这也适用于继承的列.
hybrid_propery
extention如果您还想包含hybrid_property
属性,则以下内容将起作用:
from sqlalchemy import inspect
from sqlalchemy.ext.hybrid import hybrid_property
def publics_to_dict(self) -> {}:
dict_ = {}
for key in self.__mapper__.c.keys():
if not key.startswith('_'):
dict_[key] = getattr(self, key)
for key, prop in inspect(self.__class__).all_orm_descriptors.items():
if isinstance(prop, hybrid_property):
dict_[key] = getattr(self, key)
return dict_
Run Code Online (Sandbox Code Playgroud)
我假设您在列中标记了一个开头_
,表示您要隐藏它们,或者因为您通过某个访问属性,hybrid_property
或者您根本不想显示它们.参考
如果您还想包含它们,Tippall_orm_descriptors
也会返回hybrid_method和AssociationProxy.
每一个答案(如1,2),其基于所述__dict__
属性简单地返回该对象的所有属性.这可能是您想要的更多属性.就像我很遗憾这包含_sa_instance_state
或您在此对象上定义的任何其他属性.
每一个答案(如1,2),这是基于该dict()
功能仅适用于SQLAlchemy的通过返回行对象session.execute()
不是您所定义的工作,像类class User
的问题.
该解决答案是基于row.__table__.columns
一定不会工作.row.__table__.columns
包含SQL数据库的列名.这些只能等于python对象的属性名称.如果没有,你会得到一个AttributeError
.答案(如1,2)的基础上class_mapper(obj.__class__).mapped_table.c
这是相同的.
您正在迭代的表达式求值为模型对象列表,而不是行.所以以下是它们的正确用法:
for u in session.query(User).all():
print u.id, u.name
Run Code Online (Sandbox Code Playgroud)
你真的需要把它们转换成dicts吗?当然,有很多方法,但是你不需要SQLAlchemy的ORM部分:
result = session.execute(User.__table__.select())
for row in result:
print dict(row)
Run Code Online (Sandbox Code Playgroud)
更新:看看sqlalchemy.orm.attributes
模块.它有一组用于处理对象状态的函数,尤其对您有用instance_dict()
.
使用 python 3.8+,我们可以使用 dataclass 和asdict
它附带的方法来做到这一点:
from dataclasses import dataclass, asdict
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, String, Integer, create_engine
Base = declarative_base()
engine = create_engine('sqlite:///:memory:', echo=False)
@dataclass
class User(Base):
__tablename__ = 'users'
id: int = Column(Integer, primary_key=True)
name: str = Column(String)
email = Column(String)
def __init__(self, name):
self.name = name
self.email = 'hello@example.com'
Base.metadata.create_all(engine)
SessionMaker = sessionmaker(bind=engine)
session = SessionMaker()
user1 = User("anurag")
session.add(user1)
session.commit()
query_result = session.query(User).one() # type: User
print(f'{query_result.id=:}, {query_result.name=:}, {query_result.email=:}')
# query_result.id=1, query_result.name=anurag, query_result.email=hello@example.com
query_result_dict = asdict(query_result)
print(query_result_dict)
# {'id': 1, 'name': 'anurag'}
Run Code Online (Sandbox Code Playgroud)
关键是使用@dataclass
装饰器,并用它的类型(行的: str
部分name: str = Column(String)
)注释每一列。
另请注意,由于email
未注释,因此不包含在query_result_dict
.
我发现这篇文章是因为我正在寻找一种方法将SQLAlchemy行转换为dict.我正在使用SqlSoup ...但答案是由我自己建立的,所以,如果它可以帮助这里的人是我的两分钱:
a = db.execute('select * from acquisizioni_motes')
b = a.fetchall()
c = b[0]
# and now, finally...
dict(zip(c.keys(), c.values()))
Run Code Online (Sandbox Code Playgroud)
请参阅Alex Brasetvik的答案,您可以使用一行代码来解决问题
row_as_dict = [dict(row) for row in resultproxy]
Run Code Online (Sandbox Code Playgroud)
在Alex Brasetvik的答案的评论部分,SQLAlchemy的创建者zzzeek表示这是问题的"正确方法".
您可以尝试以这种方式进行。
for u in session.query(User).all():
print(u._asdict())
Run Code Online (Sandbox Code Playgroud)
它在查询对象中使用内置方法,该方法返回查询对象的字典对象。
参考:https : //docs.sqlalchemy.org/en/latest/orm/query.html
我刚刚处理这个问题几分钟了。标记为正确的答案不尊重字段的类型。解决方案来自字典化学添加一些有趣的功能。 https://pythonhosted.org/dictalchemy/ 我刚刚测试过它并且工作正常。
Base = declarative_base(cls=DictableModel)
session.query(User).asdict()
{'id': 1, 'username': 'Gerald'}
session.query(User).asdict(exclude=['id'])
{'username': 'Gerald'}
Run Code Online (Sandbox Code Playgroud)
class User(object):
def to_dict(self):
return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])
Run Code Online (Sandbox Code Playgroud)
那应该有效。
1.3 文档提供了一个非常简单的解决方案: KeyedTuple._asdict()
def to_array(rows):
return [r._asdict() for r in rows]
def query():
data = session.query(Table).all()
return to_array(data)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
184308 次 |
最近记录: |