Share sqlalchemy models between flask and other apps

flask-sqlalchemy models in separate file
flask-sqlalchemy mysql tutorial
flask-sqlalchemy existing database
flask-sqlalchemy query
flask-sqlalchemy vs sqlalchemy
flask-sqlalchemy join
install flask-sqlalchemy
db = sqlalchemy(app)

I have a running Flask application that is set up according to a combination of best practices we found online and in Miguel Grinberg's "Flask Web Development" book.

We now need a second Python application, that is NOT a web app, and that needs access to the same models as the Flask application. We wanted to re-use the same models ofcourse, so both apps can benefit from the shared code.

We have removed dependencies on the flask-sqlalchemy extention (which we used before, when we had just the Flask application). And replaced it with the SQLalchemy Declarative extension described here, which is a bit simpler (Flask-SQLalchemy adds a few specific things to standard SQLAlchemy)

In line with the example we have created a database.py file in the root. In our case there are two things different from the Declarative extension example: I put the engine and session in a class, because all of our models use db.session, instead of db_session, and I pass a dictionary with configuration values to the init(), so that I can re-use this database.py from both Flask as well as another application, using a different configuration. it looks like this:

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base


class Database(object):

    def __init__(self, cfg):
        self.engine = create_engine(cfg['SQLALCHEMY_DATABASE_URI'], convert_unicode=True)
        self.session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=self.engine))

    class Model(object):
        pass

Base = declarative_base()

So now we come to the actual problem. Flask creates a dictionary-like object containing configuration options, and adds them as a property to the app-instance. It loads them from an instance folder, a config.py in the root of the site and from environment variables. I need to pass in the configuration dictionary from Flask, so I need Flask to FIRST load and assemble the configuration, and after that initialise the database, and have a (configured) db object in the root of the app file. However, we follow the Application factory pattern, so we can use different configurations for different situations (test, production, development).

This means our app/__init__.py looks something like this (simplified):

from flask import Flask
from database import Database
from flask.ext.mail import Mail
from flask_bcrypt import Bcrypt
from config import config

mail = Mail()
bcrypt = Bcrypt()


def create_app(config_name):

    app = Flask(__name__, instance_relative_config=True)

    if not config_name:
        config_name = 'default'
    app.config.from_object(config[config_name])
    app.config.from_pyfile('config.py')
    config[config_name].init_app(app)

    db = Database(app.config)

    mail.init_app(app)
    bcrypt.init_app(app)

    @app.teardown_appcontext
    def shutdown_session(exception=None):
        db.session.remove()

    from main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    return app

But the db (that the models import from ..), now needs to be inside the create_app() function, because that's where Flask loads the configuration. If I would instantiate the db object outside of the create_app() function, it will be importable from the models, but it is not configured!

an example model looks like this, and as you can see, it expects a "db" in the root of the app:

from . base_models import areas
from sqlalchemy.orm import relationship, backref
from ..utils.helper_functions import newid
from .. import db


class Areas(db.Model, areas):
    """Area model class.
    """
    country = relationship("Countries", backref=backref('areas'))

    def __init__(self, *args, **kwargs):
        self.area_id = newid()
        super(Areas, self).__init__(*args, **kwargs)

    def __str__(self):
        return u"{}".format(self.area_name).encode('utf8')

    def __repr__(self):
        return u"<Area: '{}'>".format(self.area_name).encode('utf8')

So my question is, how can I have a db instance that can be configured externally (by either Flask or another app), and still use the Application Factory Pattern?

edit: The code-example was incorrect, it had an import for Flask-SQLalchemy which was replaced by from database import Database. Sorry for any confusion.

The Flask-SQLAlchemy extension, like most Flask extensions, should be created outside the factory, then initialized in the factory using init_app. This is so that you can use the db object before an app is created.

db = SQLAlchemy()

def create_app():
    app = Flask(__name__)
    db.init_app(app)
    return app

Your Flask app, like any properly designed Python project, should be an installable package. This is simple to do: make sure your project layout makes sense, then add a basic setup.py file.

project/
    my_flask_package/
        __init__.py  # at the most basic, this contains create_app and db
    setup.py
from setuptools import setup, find_packages

setup(
    name='my_flask_package',
    version='1.0',
    packages=find_packages(),
    install_requires=['flask', 'flask-sqlalchemy'],
)
$ python setup.py sdist

Now you can install your Flask app, along with it's database, for use in other projects. Install and import it in your second project's virtualenv, then create and push an app to initialize it.

$ pip install my_flask_package-1.0.tar.gz
from my_flask_package import db, create_app
create_app().app_context().push()
db.session.query(...)

If you're concerned about overhead involved in creating your application, you could add arguments to the create_app function to control what gets initialized. For most cases this shouldn't be an issue though.

python, The Flask-SQLAlchemy extension, like most Flask extensions, should be created outside the factory, then initialized in the factory using init_app . This is so that  Similar to the core SQLAlchemy package, Flask-SQLAlchemy provides an ORM for us to modify application data by easily creating defined models. Regardless of what your database of choice might be, Flask-SQLAlchemy will ensure that the models we create in Python will translate to the syntax of our chosen database.

For other people venturing in this direction. There is quite a good blog post and a link to a library that offers Flask-SQLAlchemy like advantages, without linking SQLAlchemy to Flask directly.

A word of warning however; I have tried to use Alchy, but still couldn't quite figure out how to integrate it into both Flask and a non-web-app, so I went with the accepted answer by davidism to this question. Your mileage may vary.

What is the best way to share SQLAlchemy models between two , For example, I have a Flask app where I would like to use some models, in the Flask project and create a RESTFul API and use that api from other projects, the  Look at the differences between Flask and Django and learn how to create a Flask app with SQLAlchemy, PostgreSQL and Alembic. Flask is one of the most popular web frameworks for Python. A key contrast between Flask and Django (the other framework) is that the latter comes with several out-of-the-box tools that make configuration much quicker.

I ran into the same problem.

If you turn on "SQLALCHEMY_ECHO" you'll likely see that a new transaction is started but the corresponding COMMIT/ ROLLBACK is missing.

For what i found out, it has something to do with two SQLAlchemy instances which you also create, once in your model file and once in your web.py. Most likely it's because you interact with your web.py's session and if you query your models there is some context switched which will receive the COMMIT.

I fixed the issue by importing "db" from models and then init it by calling db.init_app(app). According to the logs, committing now works fine.

The @app.teardown_appcontext shouldn't be necessary as it is set up in Flask-SQLAlchemy's SQLAlchemy class (https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/init.py)

How to share SQLAlchemy models between a python script and a , You can create a python module where you store your sqlalchemy model. Your script and your application why install it in each virtual  python - transaction - Share sqlalchemy models between flask and other apps python sql flask (3) For other people venturing in this direction. There is quite a good blog post and a link to a library that offers Flask-SQLAlchemy like advantages, without linking SQLAlchemy to Flask directly.

You can easily share. I will show how. Considering this Flask app:

.
├── config.py
├── db
│   └── test.db
├── do_somenthing2.py ============> Here is run some script 2
├── do_something.py   ============> Here is run some script
├── machinelearning
│   ├── models
│   │   ├── restore.py
│   │   ├── train.py
│   │   └── utils.py
│   └── save
│       └── test.ckpt
├── runserver.py ============> Here is run your app
├── test.py
└── web
    ├── __init__.py
    ├── api
    │   ├── __init__.py
    │   ├── app.py  ============> Here is app = Flask(__name__)
    │   ├── client.py
    │   ├── models.py ==========> Here is db = SQLAlchemy(app)
    │   ├── sample.json
    │   └── utils.py
    └── frontend
        ├── __init__.py
        └── routes.py

runserver.py

import os

from config import DEBUG

from web.api.app import app
from web.api.client import *

if __name__ == "__main__":
    app.run(debug=DEBUG)

OK. Now you want do use the same models to do another thing. For example: train a machine, serve and save in database (ORM) using the same models.

You can import the app and use the app.test_request_context(). Like that:

do_something.py

from web.api.app import app from web.api.models import db, user

def do_something():
    q = db.session.query(User)\
        .filter(User.Name.ilike('Andre'))
    for i in q.all():
        print (i.Name)    

with app.test_request_context():
    do_something()

do_something2.py (real example)

from web.api.app import app
from web.api.models import *

def save(df):

    passengers = []

    records = df.to_dict('records')

    for row in records:
        p = Passenger(row)
        passengers.append(p)

    for p in passengers:
        db.session.add(p)

    db.session.commit()

from ml.models import train, restore

with app.test_request_context():
    print ('Trainning model. It will take a while... (~ 5 minutos)')
    train.run()
    print ('Saving model...')
    save(restore.run())
    print ('Saved!')

Many answers recommend use (Importing files from different folder):

import sys
sys.path.append('../')

But I disagree when you have a Flask app and other scripts, because you will get crazy solving the relative references.

The approach to install your Flask app, along with it's database, for use in other projects, is another option.

Here you can find a documentation about the packages and modules.

Packages are a way of structuring Python’s module namespace by using "dotted module names". For example, the module name A.B designates a submodule named B in a package named A. Just like the use of modules saves the authors of different modules from having to worry about each other’s global variable names, the use of dotted module names saves the authors of multi-module packages like NumPy or Pillow from having to worry about each other’s module names.

Connect Flask to a Database with Flask-SQLAlchemy, Use Flask-SQLAlchemy to have your Flask app interact with a database. If you'​re into some next-level database shit, there are a few other pro-mode configuration from flask import Flask from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() Create a models.py file in our application directory. [AF] Flask-SqlAlchemy model sharing and docker I have just started working on a medium sized app. The Web part will be handled by flask, but there is a secondary part to this application that are a collection of data generating scripts.

Document how to use plain SQLAlchemy models with the Flask , app.py from flask import Flask from models import Base, User from I'd love to bring my stuff back to Flask-SQLAlchemy so that I can integrate with other Enable sharing of fields/methods between model classes #157. [AF]Using flask-sqlalchemy with flask-mqtt and app factories Does anyone have these things working together? Until I added the app factory, everything worked fine, but afterwards, when the @mqtt.on_message() function runs it doesn't have an app context, which makes sqlalchemy stop working.

SQLAlchemy in Flask, It allows you to define tables and models in one go, similar to how Django works. In addition Here's the example database.py module for your application: from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session,  I'm currently trying to use SQLAlchemy along with the Flask-SQLAlchemy extension to interface with the databases, but I'm struggling to find a way to allow the Models I define in my app to dynamically switch context from one client database to another, depending on the client. On the Flask-SQLAlchemy site, a simple example is shown along the

Quickstart, Furthermore it provides a class called Model that is a declarative base which can be used from flask import Flask from flask_sqlalchemy import SQLAlchemy app of an application that uses two tables that have a relationship to each other:. Example Flask+SQLAlchemy Project. This example project demos integration between Graphene, Flask and SQLAlchemy. The project contains two models, one named Department and another named Employee. Getting started. First you'll need to get the source of the project. Do this by cloning the whole Graphene-SQLAlchemy repository:

Comments
  • @dgilland may be able to provide an answer on integrating Alchy with both Flask and a non-web-app