6

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

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958

4 Answers4

4

You can use SQLAlchemy-Utils for this.

from sqlalchemy import create_engine
from sqlalchemy_utils import database_exits,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.

1

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?

NicoNing
  • 3,076
  • 12
  • 23
1

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()
    ...
Adán Escobar
  • 1,729
  • 9
  • 15
0

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

Daniel
  • 131
  • 1
  • 9