flask, alembic and blueprints

For some time I could easily do without autogenerated migrations. Now I wanted them and I wanted to use Flask and not Django. I started, very naively, by installing and importing either flask-alembic and flask-migrate but they all seemed (at that time) to support patterns that I didn’t want (e.g. manager, single models.py) or couldn’t understand. At some points I didnt’t get migrations to work at all or they were empty or blueprints wouldn’t work or…

What I wanted was
* a folder “models” containing all models with a file for each model
* plain alembic
* a single start file with my setup and configs

After installing alembic via pip migrations didn’t work and even importing model in env.py didn’t solve it, fiddeling with target_metadata didn’t help as well as several other solutions outlined in StackOverflow. So here is what worked for me:

In my start/setup file (start.py in my case) has a function:


start_app():
app = Flask(__name__)
# config stuff
db.init_app(app)
return app

and


if __name__ == "__main__":
app.start_app()
app.run()

The app is started by just running python start.py without need of a manager.

I created a my shared_model that all model import:


from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

This makes it easier since all the models just import this shared model and I can also put some other stuff in here that I want to have access to in my models.

The last thing to do is editing the alembic env.py:
1. Import the start_app function and start the app
2. Import the db from the shared model and initialize it
3. Configure and set target_metadata


from start import start_app
app = start_app()
from models.shared_model import db
db.init_app(app)
config.set_main_option("sqlalchemy.url", app.config["SQLALCHEMY_DATABASE_URI"])
target_metadata = db.metadata

That’s about it models go into the models folder and can be used in blueprints, alembic revision –autogenerate produces more than “pass” and the app starts like usual.

Advertisements

A sip from Flask

Lately I came to find Django a bit top heavy for one of my projects, so I chose Flask as a lighter and smaller alternative.
After fiddling with the tutorials for a bit I wanted to have a setup with several modules. Suprisingly that wasn’t as easy to do as the snippets and examples showed several options and configurations and… So, this is what worked for me. May not be the true gospel but I wanted modules to be set to certain urls like mounted apps in padrino.

This is what I came up with:

    + Project
      -- start.py
      + module1
         -- __init__.py
         -- app.py
      + module2
         -- __init__.py
         -- app.py

So module1 and 2 are two functional units which should answer to specific prefixes (localhost:5000/module1 and localhost:5000/module2) and start.py is the file to run the whole show.

I used flask-blueprint to get it all under the roof.

First let’s get the modules to behave like modules. In module1/app.py I added:

     from flask import Blueprint
     app1 = Blueprint('app1', __name__)
     ...
         @app1.route
     ...

For module2 app.py looks similar except that app1 is changed to app2.

So, now we have the blueprints, of which the project does not know yet. In fact we don’t have any app so far. All the nutrs and bolts go into start.py:

    from flask import Flask
    from module1.app import app1 
    from module2.app import app2 

     project = Flask(__name__)
     project.register_blueprint(app1, url_prefix='/path1')
     project.register_blueprint(app2. url_prefix='/path2')

     if __name__ == '__main__':
         project.run()

This is the beauty of blueprint (imho). Import the blueprint, register it and pu t it on a dedicated path.

Done. To modules in a flask-application.