Как создать новую базу данных с помощью SQLAlchemy?
С SQLAlchemy движок создается следующим образом:
from sqlalchemy import create_engine
engine = create_engine("postgresql://localhost/mydb")
Доступ к engine
завершается с ошибкой, если база данных отсутствует. Можно ли SQLAlchemy указать новую базу данных, если указанная база данных не существует?
Ответы
Ответ 1
В postgres по умолчанию обычно присутствуют три базы данных. Если вы можете подключиться как суперпользователь (например, роль postgres
), вы можете подключиться к базам данных postgres
или template1
. По умолчанию pg_hba.conf разрешает только пользователю unix с именем postgres
использовать роль postgres
, поэтому проще всего просто стать этим пользователем. Во всяком случае, создайте движок, как обычно, с пользователем, имеющим разрешения на создание базы данных:
>>> engine = sqlalchemy.create_engine("postgres://[email protected]/postgres")
Вы не можете использовать engine.execute()
, однако, поскольку postgres не позволяет создавать базы данных внутри транзакций, а sqlalchemy всегда пытается запускать запросы в транзакции. Чтобы обойти это, получите базовое соединение с движком:
>>> conn = engine.connect()
Но соединение все равно будет внутри транзакции, поэтому вам нужно завершить открытую транзакцию с помощью commit
:
>>> conn.execute("commit")
Затем вы можете продолжить создание базы данных, используя для этого правильную команду PostgreSQL.
>>> conn.execute("create database test")
>>> conn.close()
Ответ 2
См. http://sqlalchemy-utils.readthedocs.org/en/latest/database_helpers.html
from sqlalchemy import create_engine
from sqlalchemy_utils import database_exists, create_database
engine = create_engine("postgres://localhost/mydb")
if not database_exists(engine.url):
create_database(engine.url)
print(database_exists(engine.url))
Ответ 3
Можно избежать ручного управления транзакциями при создании базы данных, предоставляя функцию isolation_level='AUTOCOMMIT'
to create_engine
:
import sqlalchemy
with sqlalchemy.create_engine(
'postgresql:///postgres',
isolation_level='AUTOCOMMIT'
).connect() as connection:
connection.execute('CREATE DATABASE my_database')
Также, если вы не уверены, что базы данных не существует, существует способ игнорировать ошибку создания базы данных из-за существования путем подавления исключения sqlalchemy.exc.ProgrammingError
:
import contextlib
import sqlalchemy.exc
with contextlib.suppress(sqlalchemy.exc.ProgrammingError):
# creating database as above