запрос существующей базы данных sqlalchemy
Я использую SQLAlchmey как ORM для проекта python. Я создал несколько моделей / схем, и он работает нормально. Теперь мне нужно запросить существующую базу данных mysql, не вставлять / обновлять только инструкцию select.
Как я могу создать оболочку вокруг столов этой существующей базы данных? Я кратко просмотрел документы sqlalchemy и так, но не смог найти ничего подходящего. Всем предлагаю метод execute, где мне нужно писать сырые SQL-запросы, а я хочу использовать SQLAlchmey метод запроса таким же образом, как я использую с моделями SA.
например, если существующая БД имеет имя таблицы User, то я хочу запросить его с помощью dbsession (только операция select, возможно, с join)
3 ответов
у вас создается впечатление, что SQLAlchemy может работать только со структурой базы данных, созданной SQLAlchemy (возможно, используя MetaData.create_all()
) - это не правильно. SQLAlchemy может отлично работать с уже существующей базой данных, вам просто нужно определить свои модели для соответствия таблицам базы данных. Один из способов сделать это-использовать рефлексию, как предлагает Илья Эверила:
class MyClass(Base):
__table__ = Table('mytable', Base.metadata,
autoload=True, autoload_with=some_engine)
(что, на мой взгляд, было бы совершенно нормально для одноразовых скриптов, но может привести к невероятно разочаровывающим ошибкам в "реальное" приложение, если есть потенциал, что структура базы данных может меняться с течением времени)
другой способ-просто определить ваши модели, как обычно, заботясь о том, чтобы определить ваши модели в соответствии с таблицами базы данных, что не так сложно. Преимущество этого подхода заключается в том, что вы можете сопоставить только подмножество таблиц базы данных моделям и даже только подмножество столбцов таблицы полям вашей модели. Предположим, у вас есть 10 таблиц в базе данных, но интересует только users
таблица откуда вам только нужно id
, name
и email
поля:
class User(Base):
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
email = sa.Column(sa.String)
(обратите внимание, как нам не нужно было определять некоторые детали, которые необходимы только для испускания правильного DDL, такие как длина строковых полей или тот факт, что email
поле имеет индекс)
SQLAlchemy не будет выдавать запросы вставки / обновления, если вы не создаете или не изменяете модели в коде. Если вы хотите убедиться, что ваши запросы доступны только для чтения, вы можете создать специального пользователя в базе данных и предоставить этот пользователь выбирает только привилегии. Кроме того, можно также поэкспериментировать с откатом транзакции в коде приложения.
С некоторых пример кода:
from sqlalchemy.sql import select
from sqlalchemy import create_engine, MetaData, Table
CONN_STR = '…'
engine = create_engine(CONN_STR, echo=True)
metadata = MetaData()
cookies = Table('cookies', metadata, autoload=True,
autoload_with=engine)
cols = cookies.c
with engine.connect() as conn:
query = (
select([cols.created_at, cols.name])
.order_by(cols.created_at)
.limit(1)
)
for row in conn.execute(query):
print(row)
вы можете получить доступ к существующей таблице, используя следующий код:
from sqlalchemy.orm import Session
Base = automap_base()
Base.prepare(engine, reflect=True)
Users = Base.classes.users
session = Session(engine)
res = session.query(Users).first()