I have a web app written in python using Flask and sqlalchemy. This application runs on Heroku, and as a worker I use the ironworker extension, I have all my models defined in the models module like this:
from app import db
class Player(db.Model):
__tablename__ = 'players'
id = db.Column(db.Integer, primary_key=True)
....
type = db.Column(db.String(50))
def __init__(self, ....):
....
__mapper_args__ = {
'polymorphic_identity':'player',
'polymorphic_on':type
}
class Outfielder(Player):
__tablename__ = 'outfielders'
id = db.Column(db.Integer, db.ForeignKey('players.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity':'outfielder'
}
class Goalkeeper(Player):
__tablename__ = 'goalkeepers'
id = db.Column(db.Integer, db.ForeignKey('players.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity':'goalkeeper'
}
(Note how this imports db from app) I can create the instances of these models in my application by instantiating the models, like so:
db = SQLAlchemy(app)
gk = models.Goalkeeper('John', 'Snow', 1, 1, 3456, 67, 55, 187)
of = models.Outfielder('Gary', 'Lineker', 1, 1, 3999, 77, 78, 176)
db.session.add(gk)
db.session.add(of)
db.session.commit()
Now, what I would like to do is to be able to create the instances of these models on my external worker. The only thing that prevents me from doing so is the dependency on my app module. I don't feel like this dependency is justified and would like to find a better design approach to be able to simply export my models module to the worker and init sqlalchemy instance there and create instances of my models and save them to the database exactly the same way I can do it in the application itself.
Note that I can already access my database from the worker like this:
db = create_engine(db_url)
metadata = MetaData(db)
print "connection to the database established"
players = Table('players', metadata, autoload=True)
s = players.select()
I'm just looking for a better way of reflecting my model structure on the worker. Specifically, I'm thinking of the scenario when my models change and I'll have to maintain the code on both ends separately. If I manage to reuse the models and use declarative on both ends, then there will be no maintenance on the worker side what so ever.
The
db.Model
is a SQLAlchemydeclarative_base()
, so you can use your models like even with plain SQLAlchemy.This example works (
YourModel
is a Flask-SQLAlchemy model):You have to decouple
db
fromapp
, so you can import it without triggeringapp
creation, usingdb.init_app
.Of course you should be careful here. If you load your settings dynamically, maybe you'll load it from the wrong place with
import settings
instead ofcurrent_app.config
, but looks like you already have your worker adressed, so it is not an issue for you.Another option is create another Flask app instead of your huge web app.
From Flask-SQLAlchemy docs (http://pythonhosted.org/Flask-SQLAlchemy/api.html#flask.ext.sqlalchemy.SQLAlchemy):
EDIT: One additional thing to remember when mixing sqlalchemy session with flask-sqlalchemy models is that the flask-sqlalchemy session object is actually a subclass, with added _model_changes dictionary. As per this answer, you won't be able to commit the session if you don't add the _model_changes field: