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.
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.
All you need is to create a db connection and import your model to either flask, or non-flask app.
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.
I haven't tried this but I believe it can be done, with a little bit of work.
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 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With