I have an application design using flask
with flask-sqlalchemy
. In order to control database migrations as the models change I am using flask-migrate
to wrap alembic and use within the flask-script
management context.
I am trying to decide how to split the package distribution to achieve the following goals
- Minimal set of dependencies for the main application package
- Allow distribution of management scripts and test data for migrations and deployments perhaps using a secondary package depending on the main application module
The project structure is as follows
/
tests/ #test data
migrations/ #alembic root include env.py and alembic.ini
myapp/ # application package
setup.py
manage.py
wsgi.py
My manage.py
looks like a lot the following. This is how I avoid any alembic
or flask-migrate
dependencies in the main application package, by attaching the Migrate
object to the app in manage.py
. This also allows me to control migration configurations in the same config file as the general flask/app configurations (as the config context is pushed by the manager and with Migrate.init_app
)
from myapp import db, create_app
from myapp.database import database_manager #sub manager for creating/dropping db
from flask_migrate import Migrate, MigrateCommand
def _create_app(*args, **kwargs):
app = create_app(*args, **kwargs)
if migration is not None:
migration.init_app(app)
return app
manager = Manager(_create_app)
migration = Migrate(db = db)
manager.add_command('database', database_manager)
manager.add_command('migration', MigrateCommand)
if __name__ == "__main__":
manager.run()
The application submanager myapp.database.database_manager
enables such commands as python manage.py database create/drop/test_data
which uses sqlalchemy to create tables and populate the table with test_data from tests/
directory, but does not hook in any migration scripts, and allows me to use python manage.py migration init/revision/migrate/...
to execute flask-migrate
/alembic
commands using the application configuration context.
I am trying to distribute this application to deploy on our internal servers. There are two distribution use cases as they are currently being used
Install new server
- Install source distribution
- Create new config file to reflect DB host etc.
- Use
manage.py -c /path/to/config
to create database tables withdatabase create
- Point HTTP Server to wsgi.py
Update existing server
- Update source distribution
- Use
manage.py -c /path/to/server/config migration upgrade
to pull up the databases using the current app context - Server continues to point to wsgi.py
I would like to move this distribution to wheels/packages so that I can automate deployment on our corp intranet, So what I'm seeing here is that I would like to split my package into the main package myapp
with only Flask framework dependencies and wsgi entrypoint and myapp-manage
which includes the manage.py
, tests
, and migrations
directory.
So in the perfect world, the application will be installed on the system with global configuration files, and a specific management user will have access to the management package to perform upgrades.
Right now I am angling towards splitting the distribution with setup-app.py
and setup-manage.py
to create two seperate packages from the same source distribution. Is there a more appropriate way to package migrations and management scripts with a flask application? I have dug through the docs and while its clear how to package a flask application, distribution strategies for management scripts and migrations is less clear.