Преобразовать объект строки sqlalchemy в python dict - PullRequest
199 голосов
/ 24 декабря 2009

Существует ли простой способ перебора пар столбцов с именами и значениями?

Моя версия sqlalchemy - 0.5.6

Вот пример кода, где я пытался использовать dict (строку), но он выдает исключение, TypeError: объект «Пользователь» не повторяется

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

Ответы [ 32 ]

8 голосов
/ 25 декабря 2009

Выражение, которое вы просматриваете, переходит в список моделей объектов , а не строк Поэтому их правильное использование следующее:

for u in session.query(User).all():
    print u.id, u.name

Вам действительно нужно конвертировать их в диктанты? Конечно, есть много способов, но тогда вам не нужна ORM часть SQLAlchemy:

result = session.execute(User.__table__.select())
for row in result:
    print dict(row)

Обновление : посмотрите на модуль sqlalchemy.orm.attributes. Он имеет набор функций для работы с состоянием объекта, которые могут быть вам полезны, особенно instance_dict().

7 голосов
/ 04 августа 2012

Я нашел этот пост, потому что искал способ конвертировать строку 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()))
7 голосов
/ 03 июля 2017

См. Ответ Алекса Брасетвика , вы можете использовать одну строку кода для решения проблемы

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

В разделе комментариев к ответу Алекса Брасетвика zzzeek, ​​создатель SQLAlchemy, заявил, что это «правильный метод» для проблемы.

4 голосов
/ 21 января 2019

Вы можете попытаться сделать это таким образом.

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

Он использует встроенный метод в объекте запроса, который возвращает диктонарный объект объекта запроса.

ссылки: https://docs.sqlalchemy.org/en/latest/orm/query.html

4 голосов
/ 03 мая 2018

Вы можете преобразовать объект 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 голосов
/ 06 сентября 2018

Документы предлагают очень простое решение: ResultRow._asdict()

def to_array(rows):
    return [r._asdict() for r in rows]

def query():
    data = session.query(Table).all()
    return to_array(data)
3 голосов
/ 07 февраля 2018

Два способа:

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())
2 голосов
/ 02 апреля 2012

Вот как Эликсир это делает. Ценность этого решения состоит в том, что оно позволяет рекурсивно включать словарное представление отношений.

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
2 голосов
/ 05 ноября 2017

С помощью этого кода вы также можете добавить в свой запрос «фильтр» или «присоединиться» и эта работа!

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 голос
/ 10 февраля 2010
class User(object):
    def to_dict(self):
        return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])

Это должно сработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...