Martin Thoma
Martin Thoma

Reputation: 136389

How can I initialize the database automatically with SQLalchemy and Alembic?

Currently, I run

$ flask db init
$ flask db migrate -m "initialization"
$ flask db upgrade

if the database does not exist. I would like to run this within Python, e.g. something like

app.create_db()

so that I don't have to care about setting the database up. Is that possible?

I use the flask-sqlalchemy and flask-migrations plugins

Upvotes: 9

Views: 21361

Answers (4)

You can use SQLAlchemy-Utils for this

from sqlalchemy import create_engine
from sqlalchemy_utils import database_exists, create_database

def validate_database():
     engine = create_engine('postgres://postgres@localhost/name')
     if not database_exists(engine.url): # Checks for the first time  
         create_database(engine.url)     # Create new DB    
         print("New Database Created" + database_exists(engine.url)) # Verifies if database is there or not.
     else:
         print("Database Already Exists")

Call this method in your _init_.py file so that it checks every time your server starts.

Upvotes: 4

Adán Escobar
Adán Escobar

Reputation: 4643

I'm using alembic and sqlalchemy.

if you want to alembic automatic create your db if not exists, you can edit alembic/env.py and add a method that check if db exists:

from sqlalchemy import create_engine, exc

def create_db_if_not_exists():
    # create database if not exists
    db_uri      = os.getenv('SQLALCHEMY_DATABASE_URI')
    database    = db_uri.split('/')[-1]
    db_postgres = "/".join(db_uri.split('/')[0:-1])+"/postgres"
    try:
        engine = create_engine(db_uri)
        # Attempt to connect to the database
        with engine.connect() as conn:
            print(f'Database {database} already exists.')
    except exc.OperationalError:
        #raise Exception
        print(f'Database {database} does not exist. Creating now.')
        engine = create_engine(db_postgres) #using postgres db to connect
        ## Attempt to connect to the database
        with engine.connect() as conn:
            conn.execute("commit")
            conn.execute(f'CREATE DATABASE {database};')

then call it before execute migration:

def run_migrations_online() -> None:
    
    create_db_if_not_exists()
    ...

Upvotes: 2

NicoNing
NicoNing

Reputation: 3212

Obviously, you have installed flask-migrate, flask-sqlalchemy.

So, you can do like this:

from flask_sqlalchemy import SQLAlchemy
from flask import Flask

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
db.create_all()

API DOC: flask.ext.sqlalchemy.SQLAlchemy.create_all

but your Question has confused me. why restricted by SQLAlchemy and Alembic?

Upvotes: 2

Daniel
Daniel

Reputation: 141

There's db.create_all() but I think that when you're using migrations you should stick to migration scripts. Something to note is that if you have your migration files all set up (i.e migration folder) then all you need is flask db migrate If you're running this locally, I would stick to doing this command manually. If you're using this on a server, you should probably use a deployment script that does this for you. You can look at fabric (www.fabfile.org) for information on how to run terminal commands

Upvotes: 1

Related Questions