A potential issue with the accepted answer is that, for an initial migration, Alembic might have trouble finding a place to create the alembic_version
. This is because because op.execute("create schema foo")
is only executed after Alembic attempts to find its alembic_version
table. The error pops up as:
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.InvalidSchemaName) schema "foo" does not exist
The easy way out would be to have the alembic_version
table live in another schema passing version_table_schema
to context.configure()
(docs).
However, in many cases one might want to simultaneously (i) create a schema from scratch as part of an initial migration (e.g. to set up a testing environment) and (ii) have the alembic_version
table in the target schema. In these cases, an alternative approach is to delegate the schema creation to env.py
. Example:
# env.py
from sqlalchemy import create_engine
from bar import create_database_with_schema_if_not_exists
SQLALCHEMY_DATABASE_URI = ...
schema = "foo"
engine = create_engine(SQLALCHEMY_DATABASE_URI)
create_database_with_schema_if_not_exists(engine, schema)
...
# bar.py
import sqlalchemy
from sqlalchemy_utils import create_database, database_exists
def create_database_with_schema_if_not_exists(engine, schema):
if not database_exists(engine.url):
create_database(engine.url)
if not engine.dialect.has_schema(engine, schema):
engine.execute(sqlalchemy.schema.CreateSchema(schema))