Using Flask-SQLAlchemy in Blueprint models without reference to the app [closed] Using Flask-SQLAlchemy in Blueprint models without reference to the app [closed] flask flask

Using Flask-SQLAlchemy in Blueprint models without reference to the app [closed]


I believe the truest answer is that modular blueprints shouldn't concern themselves directly with data access, but instead rely on the application providing a compatible implementation.

So given your example blueprint.

from flask import current_app, Blueprint, render_templateflat_pages = Blueprint('flat_pages', __name__, template_folder='templates')@flat_pages.recorddef record(state):    db = state.app.config.get("flat_pages.db")    if db is None:        raise Exception("This blueprint expects you to provide "                        "database access through flat_pages.db")@flat_pages.route('/<page>')def show(page):    db = current_app.config["flat_pages.db"]    page_object = db.find_page_by_name(page)    return render_template('pages/{}.html'.format(page), page=page_object)

From this, there is nothing preventing you from providing a default implementation.

def setup_default_flat_pages_db(db):    class Page(db.Model):        name = db.Column(db.String(255), primary_key=True)        title = db.Column(db.String(255))        content = db.Column(db.String(255))        def __init__(self, name, title, content):            self.name = name            self.title = title            self.content = content    class FlatPagesDBO(object):        def find_page_by_name(self, name):            return Page.query.filter_by(name=name).first()    return FlatPagesDBO()

And in your configuration.

app.config["flat_pages.db"] = setup_default_flat_pages_db(db)

The above could be made cleaner by not relying in direct inheritance from db.Model and instead just use a vanilla declarative_base from sqlalchemy, but this should represent the gist of it.


I have similar needs of making Blueprints completely modular and having no reference to the App. I came up with a possibly clean solution but I'm not sure how correct it is and what its limitations are.

The idea is to create a separate db object (db = SQLAlchemy()) inside the blueprint and call the init_app() and create_all() methods from where the root app is created.

Here's some sample code to show how the project is structured:The app is called jobs and the blueprint is called status and it is stored inside the blueprints folder.

blueprints.status.models.py

from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()  # <--- The db object belonging to the blueprintclass Status(db.Model):    __tablename__ = 'status'    id = db.Column(db.Integer, primary_key=True)    job_id = db.Column(db.Integer)    status = db.Column(db.String(120))

models.py

from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()  # <--- The db object belonging to the root appclass Job(db.Model):    __tablename__ = 'job'    id = db.Column(db.Integer, primary_key=True)    state = db.Column(db.String(120)

factory.py

from .blueprints.status.models import db as status_db  # blueprint dbfrom .blueprints.status.routes import status_handler   # blueprint handlerfrom .models import db as root_db                      # root dbfrom flask import Flaskdef create_app():    app = Flask(__name__)    # Create database resources.    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////path/to/app.db'    root_db.init_app(app)    status_db.init_app(app)     # <--- Init blueprint db object.    with app.app_context():        root_db.create_all()        status_db.create_all()  # <--- Create blueprint db.    # Register blueprint routes.    app.register_blueprint(status_handler, url_prefix="/status")    return app

I tested it with gunicorn with gevent worker and it works. I asked a separate question about the robustness of the solution here:Create one SQLAlchemy instance per blueprint and call create_all multiple times


You asked "Are Blueprints not meant to be independent of the app and be redistributable (à la Django apps)? "

The answer is yes. Blueprints are not similar to Django App.

If you want to use different app/configurations, then you need to use "Application Dispatching" and not blueprints. Read this [1]: http://flask.pocoo.org/docs/patterns/appdispatch/#app-dispatch [1]

Also, the link here [1] http://flask.pocoo.org/docs/blueprints/#the-concept-of-blueprints [1]

It clearly says and I quote "A blueprint in Flask is not a pluggable app because it is not actually an application – it’s a set of operations which can be registered on an application, even multiple times. Why not have multiple application objects? You can do that (see Application Dispatching), but your applications will have separate configs and will be managed at the WSGI layer."