3

SQLAlchemy учебник: как начать#

 3 years ago
source link: https://solovyov.net/blog/2011/basic-sqlalchemy/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

SQLAlchemy - очевидно, лучшая ORM для питона, с обширной и подробной документацией. У такой документации есть и обратная сторона: вместо быстрого введения она подробно объясняет все базовые концепции. Мне лично легче начинать с небольших рецептов и простых примеров, а не с серьёзных трактатов - поэтому я решил написать эдакий недо-учебник, самое короткое введение в SQLAlchemy.

Уровень 1: SQL руками

Первым делом нам нужно соединение к базе, с которым можно что-то делать:

>>> from sqlalchemy import create_engine
>>> e = create_engine('mysql://user:pass@host/db')
>>> for row in e.execute('select * from table where id < %s', 2):
...     print dict(row)
{u'id': 1, u'info': u'first row'}

Очевидно, что поддерживается куда больше диалектов, например postgresql или sqlite.

Если хочется именованных параметров, можно использовать text():

>>> from sqlalchemy import text
>>> result = e.execute(text('select * from table where id < :id'), {'id': 2})

Из объектов, которые получаются итерацией результата - RowProxy - данные можно вытаскивать и индексом, и ключом, и атрибутом:

>>> row[0] == row['id'] == row.id
    True

Нужна транзакция?

>>> conn = e.connect()
>>> conn.begin()
>>> # work work work
>>> conn.commit() # try/except: conn.rollback() optionally :)

Уже с этой функциональностью работать приятнее, чем с голым DB API, тем более что параметры экранируются автоматически.

Уровень 2: SQL-выражения в питоне

Можно получить объект таблицы из базы (с автоопределением колонок) и работать с ним, если так будет удобнее:

>>> from sqlalchemy import Table, MetaData
>>> meta = MetaData(bind=e, reflect=True)
>>> table = meta.tables['table']
>>> list(e.execute(table.select(table.c.id < 2)))
    [(1, u'first row')]

Т.е. абсолютно идентичный запрос, но уже на чистом питоне, без конструирования SQL-запросов строками.

Уровень 3: ORM

Ну и если приятнее с объектами работать, которым можно поведение задавать:

>>> from sqlalchemy import orm
>>> class Table(object):
...     pass
>>> orm.Mapper(Table, meta.tables['table'])
>>> s = orm.Session(bind=e)
>>> s.query(Table).filter(Table.id < 2).first().info
    u'first row'

Тут уже можно использовать ORM по полной:

>>> class Artist(object):
...     pass
>>> orm.Mapper(Artist, meta.tables['artist'])
>>> class Album(object):
...     pass
>>> orm.Mapper(Album, meta.tables['album'])
>>> class Song(object):
...     pass
>>> orm.Mapper(Song, meta.tables['song'])
>>> s.query(Song).join(Album).filter(Album.id == 10).count()
    12L
>>> # Song первый в запросе идëт, джойны идут относительно него,
>>> # и потому тут есть явный джойн с альбомом
>>> s.query(Song.name, Album.name).join(Album).join(Artist).filter(Artist.id == 2).first()
    (u'Hex', u'Inflikted')
>>> # А так можно посмотреть, какой запрос будет сгенерирован в базу
>>> print s.query(Song.name, Album.name).join(Album).join(Artist).filter(Artist.id == 2)
SELECT song.name AS song_name, album.name AS album_name
FROM song JOIN album ON album.id = song.album_id JOIN artist ON artist.id = album.artist_id
WHERE artist.id = %(id_1)s

Еще, если использовать Session.execute(), то можно сразу передавать именованные параметры:

>>> list(s.execute('select * from table where id < :id', {'id': 2}))
    [(1, u'first row')]

Разное

Нужно сказать, что по умолчанию у Engine уже есть пул соединений, что приятно.

Метаданные с рефлексией и ранним биндингом - не совсем принятый подход, это только для маленьких наколенных скриптов и работы в шелле, скорее, а так обычно Engine к MetaData добавляют где-то отдельно, в чтении настроек, когда уже все таблицы определены (через meta.bind = e).

Сессия часто напрямик не используется, особенно в многопоточных приложениях -есть orm.scoped_session, который создаëт тред-локальную сессию.

Вот в принципе и всë, дальше есть документация. :)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK