【问题标题】:How to convert SQLAlchemy row object to a Python dict?如何将 SQLAlchemy 行对象转换为 Python 字典?
【发布时间】:2010-12-29 19:35:25
【问题描述】:

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

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

【问题讨论】:

  • 问题的标题与问题本身不匹配。根据docs Query 返回的包含多个 ORM 实体和/或列表达式的结果行使用此类返回行。 其中 此类sqlalchemy.util.KeyedTuple这是问题标题中的 row object 。但是问题中的查询使用模型(映射)类,因此 row object 的类型是模型类而不是sqlalchemy.util.KeyedTuple
  • @PiotrDobrogost 问题来自 2009 年并提到 sqlalchemy 版本 0.5.6

标签: python sqlalchemy


【解决方案1】:

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

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

【讨论】:

  • 这个帖子的最佳答案,不知道为什么其他人都提出了更复杂的解决方案。
  • 这给出了一个额外的 '_sa_instance_state' 字段,至少在 0.7.9 版本中。
  • 这样会更好:dictret = dict(row.__dict__); dictret.pop('_sa_instance_state', None)
  • 这似乎并不理想,因为正如人们指出的那样,__dict__ 包含一个必须删除的 _sa_instance_state 条目。如果您升级到未来版本并添加了其他属性,您可能必须返回并手动处理它们。如果您只想要列数据(例如,从查询中获取实例列表并将它们放入 pandas 数据框中),那么 {col.name: getattr(self, col.name) for col in self.__table__.columns} 由 Anurag Uniyal 回答(cmets 对该答案进行了重要更正)似乎更简洁并且防错。
  • 这个答案是错误的。这个问题甚至有dict(u),并正确地指出它抛出了TypeError
【解决方案2】:

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

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}

【讨论】:

  • 更简洁地说,return dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
  • @argentpepper 是的,您甚至可以使用row2dict = lambda row: dict((col, getattr(row, col)) for col in row.__table__.columns.keys()) 来使其成为真正的单行,但我更喜欢我的代码可读,水平短,垂直长
  • 如果我的列没有分配给同名的属性怎么办?即,x = Column('y', Integer, primary_key=True)?在这种情况下,这些解决方案都不起作用。
  • drdaeman 是对的,这里是正确的 sn-p:return {c.name: getattr(self, c.name) for c in self.__table__.columns}
  • 这个答案做了一个无效的假设:列名不一定匹配属性名。
【解决方案3】:

根据 cmets 中的@zzzeek:

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

for row in resultproxy:
    row_as_dict = dict(row)

【讨论】:

  • 它说'XXX对象不可迭代',我使用的是0.5.6,我通过session.query(Klass).filter().all()得到
  • 请注意,这是现代版本 SQLAlchemy 的正确答案,假设“row”是核心行对象,而不是 ORM 映射的实例。
  • 还要注意 zzzeek 是 sqlalchemy 的创建者。
  • 核心行对象与 ORM 映射实例有什么区别?这不适用于query(MyModel).all() 的行:MyModel 对象不可迭代。
  • 这个答案没有帮助,因为您没有概述“resultproxy”的方式或内容?
【解决方案4】:

在 SQLAlchemy v0.8 及更高版本中,使用inspection system

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(添加检查系统时)。
  • 这适用于 Sqlalchemy v2.0。其他答案没有。
  • 这不考虑延迟列
  • @Mark 我不清楚它们是否应该被默认排除。不过,您可以检查密钥是否不在sqlalchemy.inspect(obj).unloaded
  • @NguyenThanh 使用 SQLAlchemy v2.0 尤其令人印象深刻,因为它不存在!最新的(测试版)版本是 v1.3.0b1。
【解决方案5】:

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

【讨论】:

  • 它应该是私有的,在未来的版本中不可能被删除/更改。
  • @balki 这是quite well documented,因此不是很私密。虽然前导下划线在 Python 中通常具有该含义,但这里可能使用它是为了不与可能的元组键发生冲突。
  • 这仅适用于 KeyedTuple ,仅在查询行的特定字段时返回。即.query(Topic.name) 返回一个KeyedTuple,而.query(Topic) 返回一个没有._asdict() - Derp 的Topic。刚刚看到机顶盒的回答如下。
  • KeyedTuple 已在 1.4 中替换为 engine.Row
【解决方案6】:

正如@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'}

【讨论】:

  • 如果 python ORM 类属性与数据库列的名称不同,请尝试以下解决方案:stackoverflow.com/questions/27947294/…
  • 其实,sqlalchemy作者stackoverflow.com/a/27948279/1023033提供了一个更好的解决方案
  • 当我尝试这个时,我得到 ResultProxy 对象没有属性 '_asdict'
  • @slashdottir,您是否正在执行您的查询对象(调用.first() 方法)?
  • 这个答案做出了一个无效的假设:列名不一定与属性名匹配 - 请参阅 RazerM 的答案。
【解决方案7】:

假设将以下函数添加到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_property 扩展名

如果您还想包含 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_methodAssociationProxy 如果您还想包含它们。

其他答案的备注

每个基于 __dict__ 属性的答案(如 12 )只返回对象的所有属性。这可能是您想要的更多属性。我很伤心,这包括 _sa_instance_state 或您在此对象上定义的任何其他属性。

基于dict() 函数的每个答案(如12)仅适用于session.execute() 返回的SQLalchemy 行对象,不适用于您定义的类与问题中的class User 类似。

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

【讨论】:

  • 非常适合添加简单的方法使模型轻松 JSON 可序列化
【解决方案8】:

老问题,但由于这是 Google 中“sqlalchemy row to dict”的第一个结果,因此值得更好的回答。

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

它只是返回一个 (key, value) 元组的列表。因此,可以使用以下命令将一行转换为 dict:

在 Python

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]

【讨论】:

  • 你可以做list_of_dicts = [dict(row.items()) for row in rows]
  • 一个问题是 SQLAlchemy 在结果集中使用的列名是 table_name_column_name,如果你想要不同的名称(例如,只是 column_name),请使用 .label 方法。 session.query( MyTable.column_name.label('column_name'), ... )
  • 您好,我遇到了这个问题,请帮帮我 * datetime.datetime(2018, 11, 24, 18, 52, 50) 不是 JSON 可序列化 *
  • 似乎Row.items() 在 SQLAlchemy 1.4 中消失了。如果您在 SQLAlchemy 1.3 中使用它,则需要更改为 dict(row).items()
【解决方案9】:

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

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

这是有效的,因为在上面的代码中u 是一个类型为KeyedTuple 的对象,因为.all() 返回KeyedTuple 的列表。因此它有 _asdict() 方法,它很好地将 u 作为字典返回。

WRT @STB 的答案:AFAIK,.all() 返回的任何内容都是KeypedTuple 的列表。因此,无论是否指定列,只要您将.all() 的结果应用于Query 对象,上述方法都有效。

【讨论】:

  • 这在过去可能是正确的,但在 SQLAlchemy v1.0 .all() 返回一个 User 实例列表,所以这不起作用。
  • @RazerM,对不起,我不明白你的意思。 for 循环应该精确地循环遍历用户实例列表,将它们 (u) 转换为字典,然后打印它们...
  • User 实例没有_asdict 方法。见gist.github.com/RazerM/2eff51571b3c70e8aeecd303c2a2bc8d
  • 现在我明白了。谢谢。现在 .all() 返回 User 对象,而不是 KeyedTuple。所以 v1.0(以及更高版本,我假设)的问题是如何从 User 对象中获取字典。感谢您的澄清。
【解决方案10】:
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)

【讨论】:

  • 注意local_table和mapped_table的区别。例如,如果您在数据库中应用某种表继承(tbl_employees > tbl_managers,tbl_employees > tbl_staff),您的映射类将需要反映这一点(经理(员工),员工(员工))。 mapped_table.c 将为您提供基表和继承表的列名。 local_table 只为您提供(继承)表的名称。
  • 这样可以避免给出 '_sa_instance_state' 字段,至少在 0.8+ 版本中是这样。
  • 这个答案做了一个无效的假设:列名不一定匹配属性名。
【解决方案11】:

参考Alex Brasetvik's Answer,一行代码即可解决问题

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

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

【讨论】:

  • @Greenonline 当然,批准评论在 Alex Brasetvik 的回答下。编辑添加到他的答案的链接
  • resultproxy 是什么?
【解决方案12】:

一个非常简单的解决方案:row._asdict()

> data = session.query(Table).all()
> [row._asdict() for row in data]

【讨论】:

  • 目前它不在文档中。也许它已被弃用。
  • 我添加了 1.4 和 1.3 文档的链接。
【解决方案13】:

您正在迭代的表达式计算为模型列表对象,而不是行。所以以下是它们的正确用法:

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

【讨论】:

  • 我想将它们转换为dict,因为其他一些代码需要数据作为dict,我想要一种通用的方式,因为我不知道模型对象有哪些列
  • 当我处理它们时,我只能访问模型对象,所以我不能使用 session.execute 等
【解决方案14】:

我找到这篇文章是因为我正在寻找一种将 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()))

【讨论】:

  • 或者,如果你愿意的话..:[ dict(zip(i.keys(), i.values())) for i in b ]
  • 这是我发现的唯一有效的语法!我已经尝试了一个多小时。
  • 对于核心选择,RowProxy(此答案中为c)遵循映射协议,因此您只需调用dict(c)
【解决方案15】:

你可以试试这样。

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

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

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

【讨论】:

  • 添加更多解释可能吗?
  • 没什么好解释的。它是结果对象的内置方法。因此,无论您对所有结果还是单行都执行此操作,都有一个内置的_asdict() 方法,它本质上是使用字段值压缩字段名称并将结果作为字典返回。
  • 非常简洁,我希望它能工作,但在我的情况下 u 是一个字符串,我得到错误 ``Model' object has no attribute '_asdict'` @hllau 下面为我工作跨度>
【解决方案16】:

使用 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 装饰器,并用其类型注释每一列(name: str = Column(String) 行的: str 部分)。

还要注意,由于email 没有注释,所以它不包含在query_result_dict 中。

【讨论】:

  • 在 Python3.7 上我得到“NameError: name 'asdict' is not defined”
  • 我的错!这是python 3.8中添加的功能。修正了我的答案。
  • 如此pythonic。 3.8真棒。但是您真的不需要 init 方法吗? declarative 和 dataclass 都提供了通用的 init 方法。
  • @JeffLaughlin 这不是必需的,但我只是忠于 OP 的代码,并且还想提供一种将默认值添加到 email 字段的方法。
【解决方案17】:

使用 sqlalchemy 1.4

session.execute(select(User.id, User.username)).mappings().all()
>> [{'id': 1, 'username': 'Bob'}, {'id': 2, 'username': 'Alice'}]

【讨论】:

  • 为粗心的人提供参考:您需要使用 select 2.0 查询而不是 session.query(至少对于我的用例而言),否则这仍然行不通。
【解决方案18】:
class User(object):
    def to_dict(self):
        return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])

应该可以的。

【讨论】:

  • 如果列名以“_”开头会怎样?
  • 我想你真的不应该用下划线来命名你的列。如果你这样做,它就行不通了。如果它只是奇怪的,你知道,你可以修改它以添加那些列。
【解决方案19】:

您可以像这样将 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)

【讨论】:

    【解决方案20】:

    我刚刚处理了这个问题几分钟。 标记为正确的答案不考虑字段的类型。 解决方案来自 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'}
    

    【讨论】:

    • 这应该是新的最佳解决方案。多么幸运,我检查了每个答案都找到了这个!不再需要处理“_sa_instance_state”。
    【解决方案21】:

    两种方式:

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

    【讨论】:

      【解决方案22】:

      这就是 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
      

      【讨论】:

      • 链接已失效。下次请把相关代码也复制到这里。
      • 下次会做。如果我没记错的话,这个函数很长。
      【解决方案23】:

      使用此代码,您还可以将“过滤器”或“加入”添加到您的查询中!

      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]
      

      【讨论】:

        【解决方案24】:

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

        【讨论】:

          【解决方案25】:

          为了大家和我自己,我是这样使用它的:

          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]
          

          【讨论】:

            【解决方案26】:

            要完成@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 列,我该如何获得结果。
            【解决方案27】:

            我们可以得到一个dict中的对象列表:

            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)
            

            【讨论】:

              【解决方案28】:
              from copy import copy
              
              def to_record(row):
                  record = copy(row.__dict__)
                  del record["_sa_instance_state"]
                  return record
              

              如果不使用副本,您可能会遇到错误。

              【讨论】:

                【解决方案29】:

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

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

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

                【讨论】:

                  【解决方案30】:

                  如果您的模型表列不是 equie 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中的列存储

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2011-11-26
                    • 2019-07-21
                    • 2022-10-02
                    • 1970-01-01
                    • 2014-07-07
                    相关资源
                    最近更新 更多