Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Flask-SQLAlchemy models in Jupyter notebook

Is there any way I can import my Flask-SQLAlchemy models into a Jupyter notebook? I would like to be able to explore my models and data in the notebook.

like image 626
Stan Avatar asked Sep 29 '16 14:09

Stan


People also ask

Can Flask be used in Jupyter Notebook?

Getting Started. Before we even start thinking about beautifying our app, you should have all your functions in a separate py file as opposed to within a Jupyter Notebook. This step is necessary as Flask cannot communicate with Jupyter, but it can communicate with py files.

Can I use Flask-SQLAlchemy without Flask?

All you need is to create a db connection and import your model to either flask, or non-flask app.

Can I use SQLAlchemy with Flask?

Flask-SQLAlchemy is a Flask extension that makes using SQLAlchemy with Flask easier, providing you tools and methods to interact with your database in your Flask applications through SQLAlchemy. In this tutorial, you'll build a small student management system that demonstrates how to use the Flask-SQLAlchemy extension.


1 Answers

I haven't tried this but I believe it can be done, with a little bit of work.


tl;dr

Import the app, db, and the models you want to use. Push the app context before doing a query. If you understood all this, you're done.


In more detail

In the code which sets up your Flask app, you have a Flask-SQLAlchemy object, which is usually defined something like this:

from flask_sqlalchemy import FlaskSQLAlchemy
db = FlaskSQLAlchemy()

And somewhere else you have your models:

from db_setup import db
class MyThing(db.Model):
    thing_id = db.Column(db.Integer())

And further somewhere you have the app:

from flask import Flask
from db_setup import db
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = '...'
db.init_app(app)

Now, in your iPython notebook you have to be able to import the last two pieces above:

from app_setup import app
from models import MyThing

To run a query, you have to be in the app context (see http://flask.pocoo.org/docs/1.0/api/#flask.Flask.app_context):

with app.app_context():
    things = MyThing.query.filter(MyThing.thing_id < 100).all()

You should be able to run any query there. If I remember correctly, even outside of the with block the objects in things will still be valid, and you can retrieve their properties, etc.

If you want to explicitly commit, you can import db from where it's defined, and do

db.session.commit()

Just like using the model class name to make a query, db only works inside a context.


Technicalities

Don't worry about this section unless you got the above working but you want to tweak how you did it.

First of all, you might not want to use an app created in exactly the same way that you create it in your Flask code. For example, you might want to use a different config. Instead of importing the module where app is defined, you could just create a new Flask app in your notebook. You still have to import db (to do db.init_app(app)) and MyThing. But these modules probably don't have any configuration code in, since the configuration is all done at the level of the app.

Secondly, instead of use with, you could also explicitly do

my_context = app.app_context()
my_context.push()

then your SQLAlchemy code, and then later

my_context.pop()

This has two advantages. You can just push the context once, before using it in multiple notebook cells. The with block only works inside one cell.

Furthermore, storing the context in a variable after creating it means that you can re-use the same context. For the purposes of SQLAlchemy, the context acts a bit like a transaction. If you make a change to an object in one context, they won't apply in another context, unless you committed to the database. If you store a FlaskSQLAlchemy object in a Python variable, you won't be able to do anything with it inside a different context.

You could also store the context in a variable, then use it in multiple with blocks.

my_context = app.app_context()
with my_context.push():
    thing1 = MyThing.query().order_by(MyThing.thing_id).first()

# (Maybe in another cell)
with my_context.push()
    print thing1.thing_id

A last consideration, is that it might make sense to define your models using vanilla SQLAlchemy instead of FlaskSQLAlchemy. This would mean that you wouldn't need all the stuff above using contexts, just a database connection to create a session. This would make it much easier to import the models in non-flask code, but the tradeoff would be that it would make using them in Flask a bit harder.

like image 135
jwg Avatar answered Nov 02 '22 02:11

jwg