Рассмотрим код
для i в диапазоне (10): print «Вы увидите это 10 раз», i
Идея что вы получите список длины yx
, который вы можете (как видите выше) перебирать.
Читайте в документы python для диапазона - они рассматривают for-loop итерацию первичную usecase.
В большинстве сценариев имя столбца подходит для них. Но, возможно, вы пишете код следующим образом:
class UserModel(BaseModel):
user_id = Column("user_id", INT, primary_key=True)
email = Column("user_email", STRING)
column.name «user_email», в то время как имя поля «email», column.name не может работать как раньше.
for row in resultproxy:
row_as_dict = dict(row)
строки имеют функцию _asdict()
, которая дает dict
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'}
Вы можете преобразовать объект 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)
У меня есть вариант ответа Марко Мариани, выраженный в качестве декоратора. Основное отличие состоит в том, что он будет обрабатывать списки объектов, а также безопасно игнорировать некоторые другие типы возвращаемых значений (что очень полезно при написании тестов с использованием mocks):
@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
Выражение, которое вы повторяете, вычисляет список объектов модели , а не строк. Итак, правильное их использование:
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()
.
Вот как это делает Эликсир. Значение этого решения заключается в том, что оно позволяет рекурсивно включать в себя словарное представление отношений.
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
Старый вопрос, но поскольку это первый результат для «sqlalchemy row to dict» в Google, он заслуживает лучшего ответа.
Объект RowProxy, возвращаемый SqlAlchemy, имеет метод 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> = 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]
– Markus Meskanen
7 November 2016 в 12:03
table_name_column_name
, если вам нужны разные имена (например, только column_name
), используйте метод .label
. session.query( MyTable.column_name.label('column_name'), ... )
– Aneel
22 April 2018 в 02:01
Двумя способами:
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())
После ответа @balki, поскольку SQLAlchemy 0.8 вы можете использовать _asdict (), доступный для объектов KeyedTuple. Это дает довольно простой ответ на исходный вопрос. Просто измените в своем примере две последние строки (цикл for) для этого:
for u in session.query(User).all():
print u._asdict()
Это работает, потому что в приведенном выше коде u является объектом типа class KeyedTuple , так как .all () возвращает список KeyedTuple. Поэтому он имеет метод _asdict () , который прекрасно возвращает u в качестве словаря.
WRT ответ by @STB: AFAIK, anikong, что .all () возвращает список KeypedTuple. Следовательно, вышеизложенное работает либо при указании столбца, либо в отсутствии, если вы имеете дело с результатом .all () применительно к объекту Query.
.all()
возвращает список экземпляров User
, поэтому это не работает.
– RazerM
20 May 2016 в 15:42
User
нет метода _asdict
. См. gist.github.com/RazerM/2eff51571b3c70e8aeecd303c2a2bc8d
– RazerM
25 May 2016 в 21:08
Решение, которое также работает с наследуемыми классами:
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])}
__table__
, и этот код не учитывает такие. Это то, для чего предназначен модуль для проверки i>.
– Piotr Dobrogost
6 February 2018 в 10: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)
Я нашел этот пост, потому что искал способ преобразования строки 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()))
RowProxy
(c
в этом ответе) придерживается протокола сопоставления, поэтому вы можете просто вызвать dict(c)
.
– RazerM
20 May 2016 в 15:56
Обратитесь к Ответу от Alex Brasetvik , вы можете использовать одну строку кода для решения проблемы
row_as_dict = [dict(row) for row in resultproxy]
. В разделе комментариев ответа Алекса Брасетвика zzzeek создатель SQLAlchemy заявила, что это «правильный метод» для проблемы.
У меня нет большого опыта в этом, но, похоже, работает то, что я делаю:
dict(row)
Это кажется слишком простым (по сравнению с другими ответами здесь). Что мне не хватает?
row['ultimate answer'] = 42
. Просто использование dict()
не сохраняет порядок столбцов, но следующее выглядит следующим образом: d = OrderedDict ( ) # Добавьте каждый элемент в порядок. для k, v в row.items (): d.update ({k: v})
– Ralph Case
25 May 2016 в 17:36
Использовать систему проверки .
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
.
sqlalchemy.inspect(obj).unloaded
– RazerM
4 December 2017 в 10:05
как @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'}
.first()
)?
– Sam Bourne
5 July 2016 в 18:57
Мой прием с использованием (слишком много?) словарей:
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
Работа с флягой (включая jsonify) и flask_sqlalchemy для вывода на печать в виде JSON.
Вызвать функцию с помощью jsonify (serialize ()).
Работает со всеми запросами SQLAlchemy, которые я пробовал до сих пор (работает SQLite3)
class User(object):
def to_dict(self):
return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])
Это должно работать.
Я новый программируемый программист на Python и столкнулся с проблемами, связанными с 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)
Вот супер простой способ сделать это
row2dict = lambda r: dict(r.items())
С помощью этого кода вы также можете добавить к вашему запросу «фильтр» или «присоединиться» и эту работу!
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]
Обновление 2018-03-25:
Вы больше не можете использовать u.__dict__
, поскольку он интерпретирует его как ссылку на столбец / поле. Вместо этого используйте dict(u)
.
Исходный ответ:
Вы можете получить доступ к внутреннему __dict__
объекта SQLAlchemy, например следующему ::
for u in session.query(User).all():
print u.__dict__
dictret = dict(row.__dict__); dictret.pop('_sa_instance_state', None)
– lyfing
5 November 2014 в 09:39
, если столбец таблицы моделей не является эквивалентным столбцом 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}
, если вы используйте этот способ, вы можете получить change_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
return dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
. – argentpepper 30 March 2012 в 20:13row2dict = lambda row: dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
, чтобы сделать его настоящим одним лайнером, но я предпочитаю, чтобы мой код был читаемым, горизонтально коротким, вертикально длинным – Anurag Uniyal 30 March 2012 в 20:47x = Column('y', Integer, primary_key=True)
? Ни одно из этих решений не работает в этом случае. – Buttons840 31 May 2012 в 21:46__table__.columns.keys()
не будет работать, потому что словарные клавишиcolumns
не всегда являются строками (как требуетсяgetattr
), но, возможно, всевозможные объекты, такие какsqlalchemy.sql.expression._truncated_label
. Использованиеc.name
вместоc
работает для меня. – drdaeman 14 July 2012 в 18:49return {c.name: getattr(self, c.name) for c in self.__table__.columns}
– charlax 9 August 2012 в 14:41