Python — vars на примере SQLAlchemy

Admin Python, SQLAlchemy

Разбор python функции vars() из методов для словарей (dict).

Обширная статья по запросам в SQLAlchemy.

Многие классы python показывают содержимое в виде словаря, но при этом не являются словарем, а являются объектом класса, внутри которого может быть представлен формат данных __dict__.

Если попытаться к такому объекту обратиться с методами словаря, то будут выкидываться ошибки.

Однако, раз такие объекты имеют внутри себя атрибуты __dict__, то можно преобразовать их в словарь. А дальше работать как с обычным словарем.

Разберем на примере

Исключение

vars() не нужен, если запрашиваются конкретные колонки, например так:

check_list = db.session.query(Check.title, Check.slug, Check.category, Check.example).all()

Пример

Запрос SQLAlchemy:

response = db.session.query(UserSetting).filter_by(user_id=user_id).order_by(asc(UserSetting.name)).all()

С помощью запроса type(response) мы узнаем, что response является объектом list:

<class 'list'>

С помощью print(response) мы увидим следующее содержимое:

[<1:analyse_sp500:120:None:1597834582>, <1:brent_oil:300:None:1597834559>]

Теперь проверим содержимое отдельного элемента <> класса list:

for s in response:
    print(type(s))

Нам показывают, что это класс модели ОРМ SQLAlchemy, содержащий данные из таблицы UserSetting:

<class 'app.models.UserSetting'>

Мы не можем работать с ним методами словаря. Нам нужно преобразовать его в словарь явно. Для этого воспользуемся функцией vars() в Python:

for s in response:
    setting = vars(s)
    print(type(setting))

Так мы превратили содержимое части объекта в словарь:

<class 'dict'>

Вместо vars(s) можно использовать s.__dict__, но первый вариант, как говорится, более «питонист».

Напоследок посмотрим, что находится внутри созданного словаря:

for s in response:
    setting = vars(s)
    print(setting)

Вместо такого безликого формата данных:

<1:analyse_sp500:120:None:1597834582>

Мы увидим:

{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x11942c510>,
 'id': 2,
 'name': 'analyse_sp500',
 'percent': None,
 'timer': '120',
 'timestamp': 1597834582,
 'user_id': 1}

Теперь мы можем использовать любые методы словаря и обращаться к данным привычным образом:
setting[‘name’].

Обратить внимание!

Нельзя применить vars() или .__dict__ к классу class ‘list’.

response = db.session.query(UserSetting).filter_by(user_id=user_id).order_by(asc(UserSetting.name)).all()

# Следующее приведет к ошибке!
dicts = vars(response)

Если так сделать будет ошибка:

TypeError: vars() argument must have __dict__ attribute

И все будет верно, ведь класс list не содержит атрибуты словаря. Но в самих листах (списках), если их разбить: for x in response, то внутри будут словари и вот они содержат атрибут словаря.

Однако, мы можем сразу получить данные в словаре. Это в том случае, если мы запрос делаем с конкретизацией колонок, которые хотим забрать PriceMinute.price:

response = [r._asdict() for r in
              db.session.query(PriceMinute.price, PriceMinute.time).filter_by(ticker=ticker).order_by(
                  db.desc(PriceMinute.time)).limit(10).all()]

В данном случае мы можем сразу применить к response методы словаря.

Если _asdict нет, то иногда работает так:

query = [x for x in db.engine.execute('select * from celery_taskmeta order by date_done')]

У сайта нет цели самоокупаться, поэтому на сайте нет рекламы. Но если вам пригодилась информация, можете лайкнуть страницу, оставить комментарий или отправить мне подарок на чашечку кофе.

Добавить комментарий

Напишите свой комментарий, если вам есть что добавить/поправить/спросить по теме текущей статьи:
"Python — vars на примере SQLAlchemy"