我有一个使用Flask和sqlalchemy用python编写的Web应用程序。这个应用程序在 Heroku 上运行,作为一名工人,我使用 ironworker 扩展,我在模型模块中定义了我所有的模型,如下所示:
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'
}
(请注意如何从应用程序导入数据库) 我可以通过实例化模型在我的应用程序中创建这些模型的实例,如下所示:
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()
现在,我想做的是能够在我的外部工作线程上创建这些模型的实例。唯一阻止我这样做的是对我的应用程序模块的依赖。我觉得这种依赖关系是不合理的,并希望找到一种更好的设计方法,以便能够简单地将我的模型模块导出给 worker 并在那里初始化 sqlalchemy 实例并创建我的模型实例并将它们保存到数据库中,就像我在应用程序本身中所做的那样。
请注意,我已经可以从工作线程访问我的数据库,如下所示:
db = create_engine(db_url)
metadata = MetaData(db)
print "connection to the database established"
players = Table('players', metadata, autoload=True)
s = players.select()
我只是在寻找一种更好的方法来将我的模型结构反映在工人身上。具体来说,我正在考虑我的模型发生变化时的情况,我将不得不分别维护两端的代码。如果我设法重用模型并在两端使用声明式,那么工人方面将没有任何维护。
db.Model
是一个SQLAlchemydeclarative_base()
,所以你可以像使用普通的SQLAlchemy一样使用你的模型。
这个例子有效(YourModel
是一个Flask-SQLAlchemy模型):
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import settings
from models import YourModel
engine = create_engine(settings.SQLALCHEMY_DATABASE_URI)
Session = sessionmaker(bind=engine)
session = Session()
# do something with your session
session.query(YourModel).first()
您必须将db
与app
解耦,以便您可以使用db.init_app
在不触发app
创建的情况下导入它。
当然,在这里你应该小心。如果您动态加载设置,也许您会用import settings
而不是current_app.config
从错误的地方加载它,但看起来您已经解决了您的工作人员,所以这对您来说不是问题。
另一种选择是创建另一个 Flask 应用程序,而不是您的大型 Web 应用程序。
来自 Flask-SQLAlchemy 文档 (http://pythonhosted.org/Flask-SQLAlchemy/api.html#flask.ext.sqlalchemy.SQLAlchemy):
您仍然可以直接使用 sqlalchemy 和 sqlalchemy.orm,但请注意 Flask-SQLAlchemy 自定义只能通过 此 SQLAlchemy 类的实例。查询类默认为 BaseQuery 对于数据库。查询,数据库。Model.query_class,以及 的默认query_class db.relationship 和 db.backref.如果通过以下方式使用这些接口 sqlalchemy 和 sqlalchemy.orm 直接,默认查询类会 是斯拉尔金术的。
编辑:将sqlalchemy session与flask-sqlalchemy模型混合时要记住的另一件事是,flask-sqlalchemy session对象实际上是一个子类,添加了_model_changes字典。根据此答案,如果不添加_model_changes字段,您将无法提交会话:
def create_session(config):
engine = create_engine(config['DATABASE_URI'])
Session = sessionmaker(bind=engine)
session = Session()
session._model_changes = {}
return session