是否有一种简单的方法来迭代列名和值对?
我的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)
在我的系统输出上运行此代码:
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
答案 0 :(得分:193)
您可以访问SQLAlchemy对象的内部__dict__
,如下所示::
for u in session.query(User).all():
print u.__dict__
答案 1 :(得分:127)
我无法得到一个好的答案,所以我用它:
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}
答案 2 :(得分:64)
在SQLAlchemy v0.8及更高版本中,使用inspection system。
$container = new \Slim\Container();
$container['customError'] = function($c){
return function ($request, $response) use ($c) {
$output = ['success'=>0, 'error'=>"Custom Error Output."];
return $c['response']
->withStatus(400)
->withHeader('Content-Type', 'application/json')
->write(json_encode($output));
};
};
$app = new \Slim\App($container);
请注意,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)
是属性名称,可以与列名称不同,例如在以下情况中:
.key
此方法也适用于column_property
。
答案 3 :(得分:63)
for row in resultproxy:
row_as_dict = dict(row)
答案 4 :(得分:32)
行有_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'}
答案 5 :(得分:17)
正如@balki所说:
如果您要查询特定字段,可以使用_asdict()
方法,因为它以KeyedTuple的形式返回。
In [1]: foo = db.session.query(Topic.name).first()
In [2]: foo._asdict()
Out[2]: {'name': u'blah'}
然而,如果您没有指定列,则可以使用其他建议方法之一 - 例如@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'}
答案 6 :(得分:14)
老问题,但由于这是Google中“sqlalchemy row to dict”的第一个结果,它值得一个更好的答案。
SqlAlchemy返回的RowProxy对象具有items()方法: http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items
它只返回(键,值)元组的列表。因此可以使用以下内容将行转换为dict:
在Python&lt; = 2.6:
中rows = conn.execute(query)
list_of_dicts = [dict((key, value) for key, value in row.items()) for row in rows]
在Python中&gt; = 2.7:
rows = conn.execute(query)
list_of_dicts = [{key: value for (key, value) in row.items()} for row in rows]
答案 7 :(得分: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)
答案 8 :(得分:9)
关注@balki回答,自SQLAlchemy 0.8 以来,您可以使用_asdict(),可用于KeyedTuple对象。这为原始问题提供了一个非常简单的答案。只是,在你的例子中改变这一行的最后两行(for循环):
for u in session.query(User).all():
print u._asdict()
这是有效的,因为在上面的代码中,u是类KeyedTuple类型的对象,因为.all()返回KeyedTuple的列表。因此它有方法_asdict(),它很好地将你作为字典返回。
WRST答案@STB:AFAIK,anithong .all()返回的是KeypedTuple的列表。因此,只要您正在处理应用于Query对象的.all()的结果,如果您指定了一个列,上述工作就会起作用。
答案 9 :(得分:9)
假设以下函数将添加到class User
,以下内容将返回所有列的所有键值对:
def columns_to_dict(self):
dict_ = {}
for key in self.__mapper__.c.keys():
dict_[key] = getattr(self, key)
return dict_
与其他答案不同,只返回对象的那些属性,这些属性是对象类级别的Column
属性。因此,不包括_sa_instance_state
或任何其他属性 SQLalchemy 或您添加到对象。 Reference
编辑:忘了说,这也适用于继承的列。
hybrid_propery
延伸如果您还想包含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_
我在此假设您使用开头_
标记列,以指示您要隐藏它们,因为您通过hybrid_property
访问该属性,或者您根本不想显示它们。 Reference
Tipp all_orm_descriptors
如果您还要包含它们,也会返回hybrid_method和AssociationProxy。
基于__dict__
属性的每个答案(如1,2)只返回对象的所有属性。这可能是您想要的更多属性。就像我很遗憾,这包括_sa_instance_state
或您在此对象上定义的任何其他属性。
基于dict()
函数的每个答案(如1,2)仅适用于session.execute()
返回的 SQLalchemy 行对象不是您定义的类,例如问题中的class User
。
基于row.__table__.columns
的{{3}}肯定会不工作。 row.__table__.columns
包含SQL数据库的列名。这些只能等于python对象的属性名称。如果没有,你得到一个AttributeError
。
对于基于class_mapper(obj.__class__).mapped_table.c
的答案(例如solving answer,1),它是相同的。
答案 10 :(得分:8)
您正在迭代的表达式求值为模型对象的列表,而不是行。所以以下是它们的正确用法:
for u in session.query(User).all():
print u.id, u.name
你真的需要将它们转换成dicts吗?当然,有很多方法,但是你不需要ORM部分SQLAlchemy:
result = session.execute(User.__table__.select())
for row in result:
print dict(row)
更新:查看sqlalchemy.orm.attributes
模块。它有一组用于处理对象状态的函数,可能对您有用,尤其是instance_dict()
。
答案 11 :(得分:7)
参考Alex Brasetvik's Answer,您可以使用一行代码来解决问题
row_as_dict = [dict(row) for row in resultproxy]
在Alex Brasetvik的回答评论部分,SQLAlchemy的创建者zzzeek表示这是解决问题的“正确方法”。
答案 12 :(得分:7)
我发现这篇文章是因为我正在寻找一种将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()))
答案 13 :(得分:6)
使用python 3.8+,我们可以使用数据类以及其随附的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'}
关键是使用@dataclass
装饰器,并用其类型(: str
行的name: str = Column(String)
部分)注释每一列。
还请注意,由于email
未被注释,因此它不包含在query_result_dict
中。
答案 14 :(得分:4)
您可以尝试以这种方式进行。
for u in session.query(User).all():
print(u._asdict())
它在查询对象中使用内置方法,该方法返回查询对象的字典对象。
答案 15 :(得分:4)
您可以将sqlalchemy对象转换为此类字典并将其作为json / dictionary返回。
助手功能:
import json
from collections import OrderedDict
def asdict(self):
result = OrderedDict()
for key in self.__mapper__.c.keys():
if getattr(self, key) is not None:
result[key] = str(getattr(self, key))
else:
result[key] = getattr(self, key)
return result
def to_array(all_vendors):
v = [ ven.asdict() for ven in all_vendors ]
return json.dumps(v)
驱动程序功能:
def all_products():
all_products = Products.query.all()
return to_array(all_products)
答案 16 :(得分:3)
文档提供了一个非常简单的解决方案:ResultRow._asdict()
def to_array(rows):
return [r._asdict() for r in rows]
def query():
data = session.query(Table).all()
return to_array(data)
答案 17 :(得分:2)
我刚刚处理这个问题几分钟。 标记为正确的答案不尊重字段的类型。 解决方案来自 dictalchemy 添加一些有趣的特征。 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'}
答案 18 :(得分:2)
这是Elixir如何做到的。这个解决方案的价值在于它允许递归地包括关系的字典表示。
def to_dict(self, deep={}, exclude=[]):
"""Generate a JSON-style nested dict/list structure from an object."""
col_prop_names = [p.key for p in self.mapper.iterate_properties \
if isinstance(p, ColumnProperty)]
data = dict([(name, getattr(self, name))
for name in col_prop_names if name not in exclude])
for rname, rdeep in deep.iteritems():
dbdata = getattr(self, rname)
#FIXME: use attribute names (ie coltoprop) instead of column names
fks = self.mapper.get_property(rname).remote_side
exclude = [c.name for c in fks]
if dbdata is None:
data[rname] = None
elif isinstance(dbdata, list):
data[rname] = [o.to_dict(rdeep, exclude) for o in dbdata]
else:
data[rname] = dbdata.to_dict(rdeep, exclude)
return data
答案 19 :(得分:2)
使用此代码,您还可以添加到您的查询“过滤器”或“加入”,这项工作!
ObjectStream<DocumentSample> bin
= ObjectStreamUtils.createObjectStream(categoryStreams.toArray(new ObjectStream[0]));
答案 20 :(得分:2)
两种方式:
1
dst <- dist(Model_Results,method="binary")
hca <- hclust(dst)
clust <- cutree(hca,k=40)
dend <-as.dendrogram(hca)
library(dendextend)
clust.cutree <- dendextend:::cutree(dend, k=40, order_clusters_as_data = FALSE)
idx <- order(as.numeric(names(clust.cutree)))
clust.cutree <- clust.cutree[idx]
tbl <- table(clust, clust.cutree)
lbls <- apply(tbl,2,which.max)
dend1 <- color_branches(dend, k = 40, groupLabels = lbls)
plot(dend1)
2
for row in session.execute(session.query(User).statement):
print(dict(row))
答案 21 :(得分:1)
我们可以获得字典中的对象列表:
def queryset_to_dict(query_result):
query_columns = query_result[0].keys()
res = [list(ele) for ele in query_result]
dict_list = [dict(zip(query_columns, l)) for l in res]
return dict_list
query_result = db.session.query(LanguageMaster).all()
dictvalue=queryset_to_dict(query_result)
答案 22 :(得分:1)
我对Marco Mariani的答案有所不同,表达为装饰者。主要区别在于它将处理实体的列表,以及安全地忽略其他类型的返回值(在使用模拟编写测试时非常有用):
@decorator
def to_dict(f, *args, **kwargs):
result = f(*args, **kwargs)
if is_iterable(result) and not is_dict(result):
return map(asdict, result)
return asdict(result)
def asdict(obj):
return dict((col.name, getattr(obj, col.name))
for col in class_mapper(obj.__class__).mapped_table.c)
def is_dict(obj):
return isinstance(obj, dict)
def is_iterable(obj):
return True if getattr(obj, '__iter__', False) else False
答案 23 :(得分:1)
class User(object):
def to_dict(self):
return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])
这应该有效。
答案 24 :(得分:0)
您在项目中的任何地方都需要它,我非常感谢@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”方法,都将在那里。
答案 25 :(得分:0)
要完成@Anurag Uniyal的回答,以下是一种将递归地遵循关系的方法:
from sqlalchemy.inspection import inspect
def to_dict(obj, with_relationships=True):
d = {}
for column in obj.__table__.columns:
if with_relationships and len(column.foreign_keys) > 0:
# Skip foreign keys
continue
d[column.name] = getattr(obj, column.name)
if with_relationships:
for relationship in inspect(type(obj)).relationships:
val = getattr(obj, relationship.key)
d[relationship.key] = to_dict(val) if val else None
return d
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
first_name = Column(TEXT)
address_id = Column(Integer, ForeignKey('addresses.id')
address = relationship('Address')
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
city = Column(TEXT)
user = User(first_name='Nathan', address=Address(city='Lyon'))
# Add and commit user to session to create ids
to_dict(user)
# {'id': 1, 'first_name': 'Nathan', 'address': {'city': 'Lyon'}}
to_dict(user, with_relationship=False)
# {'id': 1, 'first_name': 'Nathan', 'address_id': 1}
答案 26 :(得分:0)
def to_dict(row):
return {column.name: getattr(row, row.__mapper__.get_property_by_column(column).key) for column in row.__table__.columns}
for u in session.query(User).all():
print(to_dict(u))
此功能可能会有所帮助。 当属性名称不同于列名称时,找不到更好的解决方案。
答案 27 :(得分:0)
使用字典推导
for u in session.query(User).all():
print ({column.name: str(getattr(row, column.name)) for column in row.__table__.columns})
答案 28 :(得分:0)
为了所有人和我自己,这是我的用法:
import Foundation
import MapKit
class CustomPin: NSObject, MKAnnotation
{
var coordinate: CLLocationCoordinate2D
var title: String?
init(pinTitle: String, location: CLLocationCoordinate2D) {
self.title = pinTitle
self.coordinate = location
}
}
func setPin(location: CLLocationCoordinate2D)
{
let pin = CustomPin(pinTitle:"" ,location: location)
self.mapView.addAnnotation(pin)
self.mapView.delegate = self
print(location.latitude)
print(location.longitude)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "customAnnotation")
annotationView.image = UIImage(named: "marker")
annotationView.canShowCallout = true
annotationView.detailCalloutAccessoryView = addressLabel
return annotationView
}
答案 29 :(得分:0)
以字典的形式返回此:class:DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.getParams().setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, connectionTimeout);
... // some more other setting.
httpClient.getParams().setParameter(HttpProtocolParams.HTTP_CONTENT_CHARSET, contentCharset);
的内容
httpClient = HttpClientBuilder.create().build();
Builder builder = RequestConfig.custom();
builder.setConnectionRequestTimeout(connectionTimeout);
... // some other setting
// no function to set the content charset
答案 30 :(得分:0)
如果您的模型表列不等于mysql列。
例如:
class People:
id: int = Column(name='id', type_=Integer, primary_key=True)
createdTime: datetime = Column(name='create_time', type_=TIMESTAMP,
nullable=False,
server_default=text("CURRENT_TIMESTAMP"),
default=func.now())
modifiedTime: datetime = Column(name='modify_time', type_=TIMESTAMP,
server_default=text("CURRENT_TIMESTAMP"),
default=func.now())
需要使用:
from sqlalchemy.orm import class_mapper
def asDict(self):
return {x.key: getattr(self, x.key, None) for x in
class_mapper(Application).iterate_properties}
如果使用这种方式,则可以得到Modify_time和create_time均为None
{'id': 1, 'create_time': None, 'modify_time': None}
def to_dict(self):
return {c.name: getattr(self, c.name, None)
for c in self.__table__.columns}
因为类属性名称与mysql中的列存储不相同
答案 31 :(得分:0)
我是一名新兴的Python程序员,遇到了使用Joined表获取JSON的问题。使用这里的答案中的信息,我构建了一个函数,将合理的结果返回给JSON,其中包含表名,避免别名,或者字段发生冲突。
只需传递会话查询的结果:
test = Session()。query(VMInfo,Customer).join(Customer).order_by(VMInfo.vm_name).limit(50).offset(10)
json = sqlAl2json(test)
def sqlAl2json(self, result):
arr = []
for rs in result.all():
proc = []
try:
iterator = iter(rs)
except TypeError:
proc.append(rs)
else:
for t in rs:
proc.append(t)
dict = {}
for p in proc:
tname = type(p).__name__
for d in dir(p):
if d.startswith('_') | d.startswith('metadata'):
pass
else:
key = '%s_%s' %(tname, d)
dict[key] = getattr(p, d)
arr.append(dict)
return json.dumps(arr)
答案 32 :(得分:-1)
也适用于继承类的解决方案:
from itertools import chain
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Mixin(object):
def as_dict(self):
tables = [base.__table__ for base in self.__class__.__bases__ if base not in [Base, Mixin]]
tables.append(self.__table__)
return {c.name: getattr(self, c.name) for c in chain.from_iterable([x.columns for x in tables])}
答案 33 :(得分:-1)
在大多数情况下,列名适合它们。但也许您编写如下代码:
class UserModel(BaseModel):
user_id = Column("user_id", INT, primary_key=True)
email = Column("user_email", STRING)
column.name“user_email”,而字段名称为“email”,column.name无法像以前一样正常工作。
答案 34 :(得分:-2)
Python 3.6.8 +
内置的str()
方法自动将datetime.datetime对象转换为iso-8806-1。
print(json.dumps([dict(row.items()) for row in rows], default=str, indent=" "))
注意:default
函数仅在发生错误时才应用于值,因此不会转换int
和float
值...除非出现错误:)
答案 35 :(得分:-2)
我对此没有多少经验,但以下似乎对我正在做的事情有用:
dict(row)
这似乎太简单了(与此处的其他答案相比)。我错过了什么?
答案 36 :(得分:-2)
这是一种超级简单的方法
row2dict = lambda r: dict(r.items())
答案 37 :(得分:-3)
我的利用(太多?)词典:
def serialize(_query):
#d = dictionary written to per row
#D = dictionary d is written to each time, then reset
#Master = dictionary of dictionaries; the id Key (int, unique from database) from D is used as the Key for the dictionary D entry in Master
Master = {}
D = {}
x = 0
for u in _query:
d = u.__dict__
D = {}
for n in d.keys():
if n != '_sa_instance_state':
D[n] = d[n]
x = d['id']
Master[x] = D
return Master
使用flask(包括jsonify)和flask_sqlalchemy运行以将输出打印为JSON。
使用jsonify(serialize())调用该函数。
适用于我迄今为止尝试的所有SQLAlchemy查询(运行SQLite3)