Python sqlalchemy query update

CRUD-операции в SQLAlchemy ORM

При использовании SQLAlchemy ORM взаимодействие с базой данных происходит через объект Session . Он также захватывает соединение с базой данных и транзакции. Транзакция неявно стартует как только Session начинает общаться с базой данных и остается открытой до тех пор, пока Session не коммитится, откатывается или закрывается.

Для создания объекта session можно использовать класс Session из sqlalchemy.orm .

 
 
from sqlalchemy import create_engine from sqlalchemy.orm import Session engine = create_engine("postgresql+psycopg2://postgres:1111@localhost/sqlalchemy_tuts") session = Session(bind=engine)

Создавать объект Session нужно будет каждый раз при взаимодействии с базой.

Конструктор Session принимает определенное количество аргументов, которые определяют режим его работы. Если создать сессию таким способом, то в дальнейшем конструктор Session нужно будет вызывать с одним и тем же набором параметров.

Чтобы упростить этот процесс, SQLAlchemy предоставляет класс sessionmaker , который создает класс Session с аргументами для конструктора по умолчанию.

 
 
from sqlalchemy.orm import Session, sessionmaker session = sessionmaker(bind=engine)

Нужно просто вызвать sessionmaker один раз в глобальной области видимости.

Получив доступ к этому классу Session раз, можно создавать его экземпляры любое количество раз, не передавая параметры.

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

Вставка(добавление) данных

Для создания новой записи с помощью SQLAlchemy ORM нужно выполнить следующие шаги:

Создадим два новых объекта Customer :

 
 
c1 = Customer( first_name = 'Dmitriy', last_name = 'Yatsenko', username = 'Moseend', email = 'moseend@mail.com' ) c2 = Customer( first_name = 'Valeriy', last_name = 'Golyshkin', username = 'Fortioneaks', email = 'fortioneaks@gmail.com' ) print(c1.first_name, c2.last_name) session.add(c1) session.add(c2) print(session.new) session.commit()

Первый вывод: Dmitriy Golyshkin .

Два объекта созданы. Получить доступ к их атрибутам можно с помощью оператора точки ( . ).

Дальше в сессию добавляются объекты.

session.add(c1) session.add(c2)

Но добавление объектов не влияет на запись в базу, а лишь готовит объекты к сохранению в следующем коммите. Проверить это можно, получив первичные ключи объектов.

Значение атрибута id обоих объектов — None . Это значит, что они еще не сохранены в базе данных.

Вместо добавления одного объекта за раз можно использовать метод add_all() . Он принимает список объектов, которые будут добавлены в сессию.

Добавление объекта в сессию несколько раз не приводит к ошибкам. В любой момент на имеющиеся объекты можно посмотреть с помощью session.new .

Наконец, для сохранения данных используется метод commit() :

После сохранения транзакции ресурсы соединения, на которые ссылается объект Session , возвращаются в пул соединений. Последующие операции будут выполняться в новой транзакции.

Сейчас таблица Customer выглядит вот так:

таблица Customer

Пока что покупатели ничего не приобрели. Поэтому c1.orders и c2.orders вернут пустой список.

Добавим еще потребителей в таблицу customers :

 
 
from sqlalchemy import create_engine from sqlalchemy.orm import Session, sessionmaker engine = create_engine("postgresql+psycopg2://postgres:1111@localhost/sqlalchemy_tuts") session = Session(bind=engine) c3 = Customer( first_name = "Vadim", last_name = "Moiseenko", username = "Antence73", email = "antence73@mail.com", ) c4 = Customer( first_name = "Vladimir", last_name = "Belousov", username = "Andescols", email = "andescols@mail.com", ) c5 = Customer( first_name = "Tatyana", last_name = "Khakimova", username = "Caltin1962", email = "caltin1962@mail.com", ) c6 = Customer( first_name = "Pavel", last_name = "Arnautov", username = "Lablen", email = "lablen@mail.com", ) session.add_all([c3, c4, c5, c6]) session.commit()

Также добавим продукты в таблицу items :

 
 
i1 = Item(name = 'Chair', cost_price = 9.21, selling_price = 10.81, quantity = 5) i2 = Item(name = 'Pen', cost_price = 3.45, selling_price = 4.51, quantity = 3) i3 = Item(name = 'Headphone', cost_price = 15.52, selling_price = 16.81, quantity = 50) i4 = Item(name = 'Travel Bag', cost_price = 20.1, selling_price = 24.21, quantity = 50) i5 = Item(name = 'Keyboard', cost_price = 20.1, selling_price = 22.11, quantity = 50) i6 = Item(name = 'Monitor', cost_price = 200.14, selling_price = 212.89, quantity = 50) i7 = Item(name = 'Watch', cost_price = 100.58, selling_price = 104.41, quantity = 50) i8 = Item(name = 'Water Bottle', cost_price = 20.89, selling_price = 25, quantity = 50) session.add_all([i1, i2, i3, i4, i5, i6, i7, i8]) session.commit()
 
 
o1 = Order(customer = c1) o2 = Order(customer = c1) line_item1 = OrderLine(order = o1, item = i1, quantity = 3) line_item2 = OrderLine(order = o1, item = i2, quantity = 2) line_item3 = OrderLine(order = o2, item = i1, quantity = 1) line_item3 = OrderLine(order = o2, item = i2, quantity = 4) session.add_all([o1, o2]) session.new session.commit()

В данном случае в сессию добавляются только объекты Order ( o1 и o2 ). Order и OrderLine связаны отношением один-ко-многим. Добавление объекта Order в сессию неявно добавляет также и объекты OrderLine . Но даже если добавить последние вручную, ошибки не будет.

Вместо передачи объекта Order при создании экземпляра OrderLine можно сделать следующее:

 
 
o3 = Order(customer = c1) orderline1 = OrderLine(item = i1, quantity = 5) orderline2 = OrderLine(item = i2, quantity = 10) o3.line_items.append(orderline1) o3.line_items.append(orderline2) session.add_all([o3,]) session.new session.commit()

После коммита таблицы orders и order_lines будут выглядеть вот так:

таблицы orders и order_lines

Если сейчас получить доступ к атрибуту orders объекта Customer , то вернется не-пустой список.

С другой стороны отношения можно получить доступ к объекту Customer , которому заказ принадлежит через атрибут customer объекта Order — o1.customer .

Сейчас у покупателя c1 три заказа. Чтобы посмотреть все пункты в заказе нужно использовать атрибут line_items объекта Order .

c1.orders[0].line_items, c1.orders[1].line_items ([, ], [, ])

Для получения элемента заказа используйте item .

 
 
for ol in c1.orders[0].line_items: ol.id, ol.item, ol.quantity print('-------') for ol in c1.orders[1].line_items: ol.id, ol.item, ol.quantity

Все это возможно благодаря отношениям relationship() моделей.

Получение данных

Чтобы сделать запрос в базу данных используется метод query() объекта session . Он возвращает объект типа sqlalchemy.orm.query.Query , который называется просто Query . Он представляет собой инструкцию SELECT , которая будет использована для запроса в базу данных. В следующей таблице перечислены распространенные методы класса Query .

Метод Описание
all() Возвращает результат запроса (объект Query ) в виде списка
count() Возвращает общее количество записей в запросе
first() Возвращает первый результат из запроса или None , если записей нет
scalar() Возвращает первую колонку первой записи или None , если результат пустой. Если записей несколько, то бросает исключение MultipleResultsFound
one Возвращает одну запись. Если их несколько, бросает исключение MutlipleResultsFound . Если данных нет, бросает NoResultFound
get(pk) Возвращает объект по первичному ключу ( pk ) или None , если объект не был найден
filter(*criterion) Возвращает экземпляр Query после применения оператора WHERE
limit(limit) Возвращает экземпляр Query после применения оператора LIMIT
offset(offset) Возвращает экземпляр Query после применения оператора OFFSET
order_by(*criterion) Возвращает экземпляр Query после применения оператора ORDER BY
join(*props, **kwargs) Возвращает экземпляр Query после создания SQL INNER JOIN
outerjoin(*props, **kwargs) Возвращает экземпляр Query после создания SQL LEFT OUTER JOIN
group_by(*criterion) Возвращает экземпляр Query после добавления оператора GROUP BY к запросу
having(criterion) Возвращает экземпляр Query после добавления оператора HAVING

Метод all()

В базовой форме метод query() принимает в качестве аргументов один или несколько классов модели или колонок. Следующий код вернет все записи из таблицы customers .

 
 
from sqlalchemy import create_engine from sqlalchemy.orm import Session engine = create_engine("postgresql+psycopg2://postgres:1111@localhost/sqlalchemy_tuts") session = Session(bind=engine) print(session.query(Customer).all())

Так же можно получить записи из таблиц items и orders .

Чтобы получить сырой SQL, который используется для выполнения запроса в базу данных, примените sqlalchemy.orm.query.Query следующим образом: print(session.query(Customer)) .

SELECT customers. ID AS customers_id, customers.first_name AS customers_first_name, customers.last_name AS customers_last_name, customers.username AS customers_username, customers.email AS customers_email, customers.address AS customers_address, customers.town AS customers_town, customers.created_on AS customers_created_on, customers.updated_on AS customers_updated_on FROM customers

Вызов метода all() на большом объекте результата не очень эффективен. Вместо этого стоит использовать цикл for для перебора по объекту Query :

Источник

Читайте также:  Тег IMG
Оцените статью