Есть ли простой способ перебора пар столбцов и значений?
Моя версия 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
python
sqlalchemy
Анураг Униял
источник
источник
sqlalchemy.util.KeyedTuple
который является объектом строки из названия вопроса. Однако запрос в вопросе использует класс модели (сопоставленный), поэтому тип объекта строки является классом модели, а неsqlalchemy.util.KeyedTuple
.Ответы:
Вы можете получить доступ к внутреннему
__dict__
объекту SQLAlchemy, например:источник
dictret = dict(row.__dict__); dictret.pop('_sa_instance_state', None)
__dict__
включает в себя_sa_instance_state
запись, которая должна быть удалена. Если вы обновитесь до будущей версии и добавите другие атрибуты, вам, возможно, придется вернуться назад и вручную обработать их. если вы хотите просто данные столбца (например, взять список экземпляров из запроса и{col.name: getattr(self, col.name) for col in self.__table__.columns}
поместить их в фрейм данных pandas), тогда ответ от Anurag Uniyal (с важными исправлениями из комментариев к этому ответу) кажется более кратким и ошибочным. доказательство.dict(u)
и правильно утверждает, что он бросаетTypeError
.Я не мог получить хороший ответ, поэтому я использую это:
Редактировать: если указанная выше функция слишком длинная и не подходит для некоторых вкусов, здесь указывается одна строка (python 2.7+)
источник
return dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
.row2dict = lambda row: dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
сделать его реальным, но я предпочитаю, чтобы мой код был читаемым, горизонтально коротким, вертикально длиннымx = Column('y', Integer, primary_key=True)
? Ни одно из этих решений не работает в этом случае.return {c.name: getattr(self, c.name) for c in self.__table__.columns}
Согласно @zzzeek в комментариях:
источник
query(MyModel).all()
: MyModel объект не повторяется.В SQLAlchemy v0.8 и новее используйте систему проверки .
Обратите внимание, что
.key
это имя атрибута, которое может отличаться от имени столбца, например, в следующем случае:Этот метод также работает для
column_property
.источник
sqlalchemy.inspect(obj).unloaded
строки имеют
_asdict()
функцию, которая дает диктантисточник
как упомянул @balki:
Этот
_asdict()
метод можно использовать, если вы запрашиваете определенное поле, потому что оно возвращается как KeyedTuple .Принимая во внимание, что если вы не укажете столбец, вы можете использовать один из предложенных методов, например, предоставленный @charlax. Обратите внимание, что этот метод действителен только для версии 2.7+.
источник
.first()
метод)?Старый вопрос, но так как это первый результат для "sqlalchemy row to dict" в Google, он заслуживает лучшего ответа.
Объект RowProxy, который возвращает SqlAlchemy, имеет метод items (): http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items
Он просто возвращает список (ключ, значение) кортежей. Таким образом, можно преобразовать строку в dict, используя следующее:
В Python <= 2.6:
В Python> = 2.7:
источник
list_of_dicts = [dict(row.items()) for row in rows]
table_name_column_name
, если вы хотите использовать разные имена (например, простоcolumn_name
), используют.label
метод.session.query( MyTable.column_name.label('column_name'), ... )
Предполагая, что следующие функции будут добавлены к
class User
следующему, вернут все пары ключ-значение всех столбцов:в отличие от других ответов возвращаются все, кроме только тех атрибутов объекта, которые являются
Column
атрибутами на уровне класса объекта. Поэтому нет_sa_instance_state
или любой другой атрибут SQLalchemy или вы добавляете к объекту включены. СсылкаРЕДАКТИРОВАТЬ: забудьте, что это также работает на унаследованных столбцах.
hybrid_propery
продлениеЕсли вы также хотите включить
hybrid_property
атрибуты, будет работать следующее:Здесь я предполагаю, что вы помечаете столбцы началом,
_
чтобы указать, что вы хотите скрыть их, потому что вы обращаетесь к атрибуту с помощьюhybrid_property
или просто не хотите их показывать. СсылкаTipp
all_orm_descriptors
также возвращает hybrid_method и AssociationProxy, если вы также хотите включить их.Замечания к другим ответам
Каждый ответ (например, 1 , 2 ), основанный на
__dict__
атрибуте, просто возвращает все атрибуты объекта. Это может быть гораздо больше атрибутов, чем вы хотите. Как мне грустно, это включает в себя_sa_instance_state
или любой другой атрибут, который вы определяете для этого объекта.Каждый ответ (например, 1 , 2 ), основанный на
dict()
функции, работает только с объектами строк SQLalchemy, возвращаемымиsession.execute()
не теми классами, с которыми вы работаете, например,class User
из вопроса.Решение ответ , который основан на
row.__table__.columns
, безусловно , не работает.row.__table__.columns
содержит имена столбцов базы данных SQL. Они могут быть равны только имени атрибута объекта python. Если нет, вы получитеAttributeError
. Для ответов (например, 1 , 2 ) основано наclass_mapper(obj.__class__).mapped_table.c
том же.источник
источник
После ответа @balki, начиная с SQLAlchemy 0.8, вы можете использовать _asdict (), доступный для объектов KeyedTuple. Это дает довольно простой ответ на оригинальный вопрос. Просто измените в вашем примере две последние строки (цикл for) на эту:
Это работает, потому что в приведенном выше коде u является объектом класса типа KeyedTuple , поскольку .all () возвращает список KeyedTuple. Поэтому у него есть метод _asdict () , который приятно возвращает вас в качестве словаря.
WRT ответ @STB: AFAIK, и что .all () возвращает список KeypedTuple. Таким образом, вышесказанное работает, если вы укажете столбец или нет, если вы имеете дело с результатом .all () применительно к объекту Query.
источник
.all()
возвращает списокUser
экземпляров, так что это не работает.User
экземпляры не имеют_asdict
метода. См. Gist.github.com/RazerM/2eff51571b3c70e8aeecd303c2a2bc8dВыражение, через которое вы перебираете, оценивает список объектов модели , а не строк. Таким образом, следующее правильное использование их:
Вам действительно нужно конвертировать их в диктовку? Конечно, есть много способов, но тогда вам не нужна ORM часть SQLAlchemy:
Обновление : посмотрите на
sqlalchemy.orm.attributes
модуль. Он имеет набор функций для работы с состоянием объекта, которые могут быть особенно полезны для васinstance_dict()
.источник
Обратитесь к ответу Алекса Брасетвика , вы можете использовать одну строку кода для решения проблемы
В разделе комментариев Ответа Алексея Брасетвика, zzzeek, создатель SQLAlchemy, заявил, что это «правильный метод» для решения проблемы.
источник
resultproxy
?Вы можете попытаться сделать это таким образом.
Он использует встроенный метод в объекте запроса, который возвращает диктонарный объект объекта запроса.
ссылки: https://docs.sqlalchemy.org/en/latest/orm/query.html
источник
_asdict()
метод, который, по сути, объединяет имена полей со значениями полей и возвращает результат в виде словаря.u
в моем случае это строка, и я получаю сообщение об ошибке: `` Модель 'не имеет атрибута "_asdict'` @hllau ниже сработало для меняЯ нашел этот пост, потому что искал способ преобразовать строку SQLAlchemy в dict. Я использую SqlSoup ... но ответ был создан мной, так что, если это могло бы помочь кому-то, вот мои два цента:
источник
RowProxy
(c
в этом ответе) придерживается протокола отображения, так что вы можете просто позвонитьdict(c)
.Вы можете преобразовать объект sqlalchemy в словарь и вернуть его как json / dictionary.
Вспомогательные функции:
Функция водителя:
источник
Два пути:
1.
2.
источник
Документы предлагают очень простое решение:
ResultRow._asdict()
источник
Вот как это делает Эликсир. Ценность этого решения состоит в том, что оно позволяет рекурсивно включать словарное представление отношений.
источник
С помощью этого кода вы также можете добавить к вашему запросу «фильтр» или «присоединиться» и эта работа!
источник
Это должно работать.
источник
У меня есть вариант ответа Марко Мариани, выраженный в качестве декоратора. Основное отличие состоит в том, что он будет обрабатывать списки сущностей, а также безопасно игнорировать некоторые другие типы возвращаемых значений (что очень полезно при написании тестов с использованием mocks):
источник
Чтобы завершить ответ @Anurag Uniyal, вот метод, который будет рекурсивно следовать отношениям:
источник
d[relationship.key] = to_dict(val,with_relationships) if val else None
В Python 3.8+ мы можем сделать это с помощью dataclass и
asdict
метода, который идет с ним:Ключ должен использовать
@dataclass
декоратор, и аннотировать каждый столбец с его типом (: str
частьname: str = Column(String)
строки).Также обратите внимание, что, так как
email
не аннотирован, он не включен вquery_result_dict
.источник
Я новичок в программировании на Python и столкнулся с проблемами при переходе на JSON с объединенными таблицами. Используя информацию из ответов, приведенных здесь, я построил функцию, которая возвращает разумные результаты в JSON, в который включены имена таблиц, избегая использования псевдонимов или столкновения полей.
Просто передайте результат запроса сеанса:
test = Session (). query (VMInfo, Customer) .join (Customer) .order_by (VMInfo.vm_name) .limit (50) .offset (10)
json = sqlAl2json (тест)
источник
если столбец таблицы вашей модели не равен столбцу mysql.
Такие как :
Нужно использовать:
если вы используете этот способ, вы можете получить modify_time и create_time как None
Потому что имя атрибута класса не совпадает с хранилищем столбцов в MySQL
источник
Вернуть содержимое этого: class:
.KeyedTuple
в качестве словаряисточник
Ради всех и меня вот как я это использую:
источник
Эта функция может помочь. Я не могу найти лучшего решения для решения проблемы, когда имя атрибута отличается от имени столбца.
источник
Он понадобится вам везде в вашем проекте, я ответил, что @anurag работает нормально. до этого момента я использовал его, но он испортит весь ваш код, а также не будет работать с изменением сущностей.
Скорее попробуйте это, унаследуйте ваш базовый класс запросов в SQLAlchemy.
после этого, где бы вы ни определили, ваш метод "as_dict" будет там.
источник
В большинстве сценариев имя столбца подходит для них. Но, возможно, вы пишете код следующим образом:
column.name «user_email», в то время как имя поля - «электронная почта», column.name не может работать хорошо, как раньше.
sqlalchemy_base_model.py
также я пишу ответ здесь
источник