将sqlalchemy行对象转换为python dict


240

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

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

3
问题的标题与问题本身不符。根据文档, 由Query返回的包含多个ORM实体和/或列表达式的行将利用此类返回行。其中,这个类sqlalchemy.util.KeyedTuple行对象从问题的称号。但是问题中的查询使用模型(映射)类,因此行对象的类型是模型类而不是sqlalchemy.util.KeyedTuple
Piotr Dobrogost

2
@PiotrDobrogost问题来自2009年,提到sqlalchemy版本0.5.6
Anurag Uniyal

Answers:


232

您可以访问__dict__SQLAlchemy对象的内部,如下所示:

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

24
最好的答案,不知道为什么其他所有人都提出了更复杂的解决方案。
戴夫·罗克斯

92
至少在版本0.7.9中,这会提供一个额外的“ _sa_instance_state”字段。
elbear 2012年

21
因此,这样做会更好:dictret = dict(row.__dict__); dictret.pop('_sa_instance_state', None)
2014年

6
这似乎并不理想,因为正如人们指出的那样,必须__dict__包含一个_sa_instance_state条目,然后必须将其删除。如果您升级到将来的版本并添加了其他属性,则可能必须返回并手动处理它们。如果您只希望列数据(例如,从查询中获取实例列表并将其放入pandas数据框中),那么{col.name: getattr(self, col.name) for col in self.__table__.columns}正如Anurag Uniyal回答的那样(对该答案的注释进行了重要的更正)似乎既简洁又有错误-证明。
kilgoretrout 2016年

14
这个答案是错误的。该问题甚至具有dict(u)并正确地指出它引发了TypeError
RazerM '18

146

我无法得到一个很好的答案,所以我用这个:

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}

17
更简洁地说,return dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
argentpepper 2012年

4
@argentpepper是的,您甚至row2dict = lambda row: dict((col, getattr(row, col)) for col in row.__table__.columns.keys())可以做一个真正的班轮,但我希望我的代码可读性强,水平短,垂直长
Anurag Uniyal 2012年

14
如果我的专栏未分配给同名属性怎么办?IE浏览器x = Column('y', Integer, primary_key=True)?在这种情况下,这些解决方案都不起作用。
Buttons840

13
drdaeman是正确的,这是正确的代码段:return {c.name: getattr(self, c.name) for c in self.__table__.columns}
charlax 2012年

5
这个答案做出了一个无效的假设:列名不一定与属性名匹配。
RazerM '16

94

按照@zzzeek的评论:

请注意,这是现代版本的SQLAlchemy的正确答案,假设“行”是核心行对象,而不是ORM映射的实例。

for row in resultproxy:
    row_as_dict = dict(row)

13
它说“ XXX对象不可迭代”,我使用的是0.5.6,我通过session.query(Klass).filter()。all()
Anurag Uniyal 09年

60
请注意,这是现代版本的SQLAlchemy的正确答案,假设“行”是核心行对象,而不是ORM映射的实例。
zzzeek

48
还要注意zzzeek是sqlalchemy的创建者。
克里斯

1
有人可以详细说明吗?我是菜鸟,别明白了。
lameei,

1
核心行对象与ORM映射的实例之间有什么区别?这对我来说无效query(MyModel).all()MyModel对象不是可重复的。
乔纳森·哈特利

81

在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)

请注意,这.key是属性名称,可以与列名称不同,例如在以下情况下:

class_ = Column('class', Text)

此方法也适用于column_property


@DukeDougal我认为这可以从v0.8开始(添加检查系统时)。
RazerM 2013年

1
这适用于Sqlalchemy v2.0。其他答案没有。
Thanh Nguyen

这不考虑延迟列
马克

1
@Mark对我来说尚不清楚默认情况下应将它们排除在外。不过,你可以检查钥匙不在sqlalchemy.inspect(obj).unloaded
RazerM

5
@NguyenThanh鉴于其不存在,使用SQLAlchemy v2.0尤其令人印象深刻!最新的(测试版)版本为v1.3.0b1。
Mark Amery

39

行有一个_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'}

它应该是私有的,在将来的版本中可能无法删除/更改。
巴尔基

2
@balki这是有据可查的,因此不是很私人。尽管一般而言,下划线在Python中具有此含义,但在这里可能将其用于不与可能的元组键冲突。
IljaEverilä17年

5
这仅适用于KeyedTuple,仅在查询行的特定字段时返回。即.query(Topic.name)返回一个KeyedTuple,而.query(Topic)返回一个没有._asdict()-Derp的Topic。刚刚看到机顶盒在下面回答。
乍得·洛

20

就像@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'}

如果蟒蛇ORM类属性有从数据库列不同的名称,尝试此解决方案:stackoverflow.com/questions/27947294/...
TaiwanGrapefruitTea

2
实际上,
sqlalchemy

当我尝试这个时,我得到的ResultProxy对象没有属性'_asdict'–
slashdottir

@slashdottir,您是否正在执行查询对象(调用.first()方法)?
Sam Bourne

1
这个答案做出了一个无效的假设:列名称不一定与属性名称匹配–请参阅RazerM的答案。
Piotr Dobrogost

18

这是个老问题,但是由于这是Google中“ sqlalchemy dict的第一个结果”,因此它应该有一个更好的答案。

SqlAlchemy返回的RowProxy对象具有items()方法:http ://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items

它只是返回(键,值)元组的列表。因此,可以使用以下命令将行转换为字典:

在Python <= 2.6中:

rows = conn.execute(query)
list_of_dicts = [dict((key, value) for key, value in row.items()) for row in rows]

在Python> = 2.7中:

rows = conn.execute(query)
list_of_dicts = [{key: value for (key, value) in row.items()} for row in rows]

13
您可以做list_of_dicts = [dict(row.items()) for row in rows]
Markus Meskanen '16

一个缺点是,SQLAlchemy在结果集中使用的列名称为table_name_column_name,如果您想要不同的名称(例如just column_name),请使用该.label方法。session.query( MyTable.column_name.label('column_name'), ... )
Aneel

嗨,我收到了这个问题,请帮助我* datetime.datetime(
2018,11,24,18,52,50

13

假设将以下函数添加到以下函数中,则以下函数将class User返回所有列的所有键值对:

def columns_to_dict(self):
    dict_ = {}
    for key in self.__mapper__.c.keys():
        dict_[key] = getattr(self, key)
    return dict_

与其他答案不同的是,仅返回对象的那些属性,而是对象的Column类级别的属性。因此,不包含SQLalchemy或您添加到对象的_sa_instance_state任何其他属性。参考

编辑:不用说,这也适用于继承的列。

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或者只是不想显示它们。参考

如果您还希望包含它们,则Tippall_orm_descriptors还返回hybrid_methodAssociationProxy

对其他答案的评论

每一个答案(如12,其基于所述)__dict__属性简单地返回该对象的所有属性。这可能是您想要的更多属性。就像我难过一样,它包含了_sa_instance_state您在此对象上定义的任何其他属性。

每一个答案(如12这是基于)dict()功能仅适用于SQLAlchemy的行对象返回的session.execute()不是您定义的工作与类一样,class User从这个问题。

解决答案是基于row.__table__.columns一定会工作。row.__table__.columns包含SQL数据库的列名。这些只能等于python对象的属性名称。如果没有,你会得到一个AttributeError。答案(如12)的基础上class_mapper(obj.__class__).mapped_table.c这是相同的。


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)

4
注意local_table和mapped_table之间的区别。例如,如果您在数据库中应用某种类型的表继承(tbl_employees> tbl_managers,tbl_employees> tbl_staff),则映射的类将需要反映这一点(Manager(Employee),Staff(Employee))。mapping_table.c将为您提供基础表和继承表的列名。local_table仅为您提供(继承)表的名称。
Michael Ekoka 2012年

至少在版本0.8+中,这避免了提供“ _sa_instance_state”字段。
伊万·西洛基

4
这个答案做出了一个无效的假设:列名不一定与属性名匹配。
RazerM '16

11

在@balki回答之后,由于SQLAlchemy 0.8,您可以使用_asdict()(可用于KeyedTuple对象)。这为原始问题提供了一个非常简单的答案。只是,在您的示例中更改此行的最后两行(for循环):

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

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

用@STB WRT回答:AFAIK,.all()返回的anithong是KeypedTuple的列表。因此,只要您处理的是应用于查询对象的.all()结果,上述方法无论是否指定列均有效。


6
过去可能是这样,但是在SQLAlchemy v1.0上会.all()返回User实例列表,因此这行不通。
RazerM

@RazerM,对不起,但我不明白您的意思。for循环应该精确地遍历User实例列表,将它们(u)转换为字典,然后打印它们……
jgbarah

3
User实例没有_asdict方法。参见gist.github.com/RazerM/2eff51571b3c70e8aeecd303c2a2bc8d
RazerM

2
现在我懂了。谢谢。现在,.all()代替了KeyedTuple,它返回User对象。因此,对于v1.0(或更高版本,我想)的问题是如何从User对象中获取字典。感谢您的澄清。
jgbarah '16

10

您要遍历的表达式的计算结果是模型对象列表,而不是行。因此,以下是它们的正确用法:

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()


2
我想将它们转换为dict,因为其他一些代码也需要数据作为dict,并且我想要一种通用的方式,因为我不知道模型对象具有哪些列
Anurag Uniyal,2009年

当我处理它们时,我只能访问模型对象,所以我不能使用session.execute等
Anurag Uniyal,2009年

8

参考Alex Brasetvik的答案,您可以使用一行代码来解决问题

row_as_dict = [dict(row) for row in resultproxy]

在Alex Brasetvik的Answer的评论部分下,SQLAlchemy的创建者zzzeek表示这是该问题的“正确方法”。


1
@Greenonline当然,批准评论是Alex Brasetvik的回答。编辑添加到他的答案的链接
NorWay

什么是resultproxy
lameei

8

您可以尝试以这种方式进行。

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

它在查询对象中使用内置方法,该方法返回查询对象的字典对象。

参考:https : //docs.sqlalchemy.org/en/latest/orm/query.html


1
补充一些解释吧?
Tiw

1
没什么可解释的了。这是结果对象上的内置方法。因此,无论您是对所有结果还是对单个行执行此操作,都存在一个内置_asdict()方法,该方法本质上用字段值压缩字段名称,并将结果作为字典返回。
马修

非常简洁,我希望它能工作,但是u在我的情况下是一个字符串,并且出现错误“模型”对象没有属性“ _asdict”`@hllau对我
有用

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()))

1
或者,如果您愿意,也可以.. :: [dict(zip(zip(i.keys(),i.values()))对于b中的i而言)]
Mychot sad

这是我发现的唯一可行的语法!我已经尝试了一个多小时了。
slashdottir 2015年

对于核心选择,RowProxyc在此答案中)遵循映射协议,因此您可以致电dict(c)
RazerM '16

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)

3

两种方式:

1。

for row in session.execute(session.query(User).statement):
    print(dict(row))

2。

selected_columns = User.__table__.columns
rows = session.query(User).with_entities(*selected_columns).all()
for row in rows :
    print(row._asdict())

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)

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

链接已死。下次,也请在此处复制相关代码。
Gus E

下次会做。如果我没记错的话,该功能相当长。
argentpepper 2015年

2

使用此代码,您还可以将“过滤器”或“连接”添加到查询中,从而完成这项工作!

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]

1
class User(object):
    def to_dict(self):
        return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])

那应该工作。


1
如果列名以“ _”开头会怎样?
Anurag Uniyal'2

4
我想您真的不应该在列名前加下划线。如果这样做,它将无法正常工作。如果您只知道这很奇怪,则可以对其进行修改以添加这些列。
单身

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

1

为了完成@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}

如果“ with_relationships”的默认值更改为false,则最好将此值传递给递归调用。即: d[relationship.key] = to_dict(val,with_relationships) if val else None
尼古拉斯·汉密尔顿

如果要基于address_id列连接用户和地址表,并从用户表中获取所有列,而仅从地址表中获取id列,则如何获得结果。
Sudhakar

1

使用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'}

关键是使用@dataclass装饰器,并用其类型(行的: str一部分name: str = Column(String))注释每一列。

另请注意,由于email未注释,因此未包含在中query_result_dict


在Python3.7上,我收到“ NameError:未定义名称'asdict'”
devnull

我的错!这是python 3.8中添加的功能。修正了我的答案。
toaruScar

如此pythonic。3.8很棒。但是您真的不需要init方法吗?声明性和数据类均提供通用的init方法。
杰夫·劳克林

0

我是一位刚入门的Python程序员,在使用Joined表访问JSON时遇到问题。使用此处答案的信息,我构建了一个函数,用于将合理的结果返回到JSON,其中包含表名,从而避免了别名或字段冲突。

只需传递会话查询的结果即可:

测试= Session()。query(VMInfo,Customer).join(Customer).order_by(VMInfo.vm_name).limit(50).offset(10)

json = sqlAl2json(测试)

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)

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中的列存储不相等


0

.KeyedTuple以字典形式返回此:class:的内容

In [46]: result = aggregate_events[0]

In [47]: type(result)
Out[47]: sqlalchemy.util._collections.result

In [48]: def to_dict(query_result=None):
    ...:     cover_dict = {key: getattr(query_result, key) for key in query_result.keys()}
    ...:     return cover_dict
    ...: 
    ...:     

In [49]: to_dict(result)
Out[49]: 
{'calculate_avg': None,
 'calculate_max': None,
 'calculate_min': None,
 'calculate_sum': None,
 'dataPointIntID': 6,
 'data_avg': 10.0,
 'data_max': 10.0,
 'data_min': 10.0,
 'data_sum': 60.0,
 'deviceID': u'asas',
 'productID': u'U7qUDa',
 'tenantID': u'CvdQcYzUM'}

0

为了所有人和我自己,这是我的用法:

def run_sql(conn_String):
  output_connection = engine.create_engine(conn_string, poolclass=NullPool).connect()
  rows = output_connection.execute('select * from db1.t1').fetchall()  
  return [dict(row) for row in rows]

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))

此功能可能会有所帮助。当属性名称不同于列名称时,找不到更好的解决方案。


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”方法都将存在。


-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不能像以前那样正常工作。

sqlalchemy_base_model.py

我也在这里写答案

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.