On Wed, Aug 22, 2012 at 2:44 PM, David McKeone <davidmcke...@gmail.com> wrote: > > > On Wednesday, August 22, 2012 2:33:01 PM UTC+1, David McKeone wrote: >> >> >> >> On Wednesday, August 22, 2012 2:23:28 PM UTC+1, Simon King wrote: >>> >>> On Wed, Aug 22, 2012 at 12:51 PM, David McKeone <davidm...@gmail.com> >>> wrote: >>> > I've been using SQLAlchemy with Flask via the Flask extension >>> > Flask-SQLAlchemy. Everything works great so far, but I foresee a >>> > potential >>> > problem once I start to use my database model outside of Flask. In the >>> > future I'd like to be able to use my models with non-Flask SQLAlchemy >>> > (a >>> > worker daemon process or with a PySide interface). "Well just use >>> > standard >>> > SQLAlchemy," you may say, " and fore-go the use of the extension". >>> > That was >>> > my first thought, but sadly some useful extensions (notably >>> > Flask-DebugToolbar) seem to like using the extension version and it is >>> > nice >>> > to be able to have Flask manage the database sessions in the way that >>> > it >>> > does. I'd like to not throw the baby out with the bath water. >>> > >>> > I realize that this is somewhat specific to Flask, but is there a way >>> > that I >>> > could do both? Can I create models with standard SQLAlchemy >>> > declarative and >>> > then somehow inject them into Flask-SQLAlchemy's way of doing things? >>> > >>> > If it helps with the solution, I don't need to use any of the Model >>> > specific >>> > methods that Flask-SQLAlchemy provides (get_or_404, paginate, etc..) >>> > and I >>> > also specify a __tablename__ for all of my models, so I don't rely on >>> > Flask-SQLAlchemy generating that for me. >>> > >>> > I took a look at the source of Flask-SQLAlchemy >>> > >>> > (https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy.py) >>> > and from what I can tell it seems that it's using Flask's signalling >>> > capabilities by customizing SQLAlchemy's session and mapper, but that >>> > is >>> > where my understanding ends (I'm still new to this whole stack, Python, >>> > Flask, SQLAlchemy) and I could use some pointers for how to proceed. >>> > >>> > >>> > To visualize what I'm talking about, here are the two types of models. >>> > A >>> > basic Flask-SQLAlchemy model looks like >>> > >>> > (http://packages.python.org/Flask-SQLAlchemy/quickstart.html#a-minimal-application): >>> > >>> > from flask import Flask >>> > from flask.ext.sqlalchemy import SQLAlchemy >>> > >>> > app = Flask(__name__) >>> > app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' >>> > >>> > db = SQLAlchemy(app) >>> > >>> > class User(db.Model): >>> > id = db.Column(db.Integer, primary_key=True) >>> > username = db.Column(db.String(80), unique=True) >>> > email = db.Column(db.String(120), unique=True) >>> > >>> > def __init__(self, username, email): >>> > self.username = username >>> > >>> > self.email = email >>> > >>> > >>> > def __repr__(self): >>> > return '<User %r>' % self.username >>> > >>> > >>> > Note the db.Model, db.Integer and db <dot> everything. >>> > >>> > The plain declarative SQLAlchemy equivalent would be >>> > (http://flask.pocoo.org/docs/patterns/sqlalchemy/): >>> > >>> > >>> > from sqlalchemy import Column Integer, String, create_engine >>> > from sqlalchemy.orm import scoped_session, sessionmaker >>> > from sqlalchemy.ext.declarative import declarative_base >>> > >>> > engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True) >>> > db_session = scoped_session(sessionmaker(autocommit=False, >>> > autoflush=False, >>> > bind=engine)) >>> > Base = declarative_base() >>> > Base.query = db_session.query_property() >>> > >>> > >>> > class User(Base): >>> > __tablename__ = 'users' >>> > >>> > id = Column(Integer, primary_key=True) >>> > name = Column(String(50), unique=True) >>> > email = Column(String(120), unique=True) >>> > >>> > def __init__(self, name=None, email=None): >>> > self.name = name >>> > self.email = email >>> > >>> > def __repr__(self): >>> > return '<User %r>' % (self.name) >>> > >>> >>> From a very quick read of the Flask-SQLAlchemy docs, I would have >>> thought you could just use your flask-based classes in non-Flask-based >>> apps without any issue. The quickstart guide that you referenced above >>> illustrates a command-line session using them, so there's no reason >>> why you couldn't do the same in a worker process. >>> >>> Have you already tried it and found that it doesn't work? >>> >>> Simon >> >> >> >> Perhaps I've missed the important bit, but my understanding is that there >> are two ways to do it: >> >> 1) Use SQLAlchemy with manual session control >> (http://flask.pocoo.org/docs/patterns/sqlalchemy/) >> 2) Use SQLAlchemy with the Flask-SQLAlchemy extension which does session >> control for you, but requires you to use it's own declarative base class, >> db.Model >> (http://packages.python.org/Flask-SQLAlchemy/quickstart.html#a-minimal-application) >> >> The problem is that other extensions give you additional features if you >> use solution #2, but not if you use solution #1, because solution #1 implies >> that you are going to do everything yourself manually. I'm fine with the >> way solution #2 handles the sessions and everything else, I just want to be >> able to use my own declarative base so that the models are more-or-less >> independent of the app that they are being used in. > > > I did a re-read of the documentation and I'm guessing this is the part of > the documentation you are referring to: > http://packages.python.org/Flask-SQLAlchemy/contexts.html > > That basically says to use: app.test_request_context() before doing what you > do, so that it can establish a new context. I suppose that does make sense, > I guess i just viewed it as being only for testing and not for application > use. I would have thought it might be strange to include Flask in a worker > daemon when it isn't actually servicing http requests. >
Disclaimer: I've never used Flask so everything I say here could be rubbish. Your question really seems to be 'How can I make Flask-SQLAlchemy work with "standard" SQLAlchemy classes?', which is probably better asked in a Flask-SQLAlchemy forum. It looks like the test_request_context method is only needed if you don't have a Flask app object available when you define your model classes. An (admittedly ugly) alternative would be to do something like this: #------------------------ from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy class Bunch(object): def __init__(self, **kwargs): self.__dict__.update(kwargs) def get_model(app=None): if app is None: app = Flask(__name__) db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True) email = db.Column(db.String(120), unique=True) def __init__(self, username, email): self.username = username self.email = email def __repr__(self): return '<User %r>' % self.username return Bunch(**locals()) if __name__ == '__main__': model = get_model() model.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' model.db.create_all() user = model.User('Joe', 'j...@example.com') model.db.session.add(user) model.db.session.commit() print model.db.session.query(model.User).all() #------------------------ Non-flask apps could just call the get_model() function and be completely unaware that flask is in use under the hood. Flask apps would pass their "app" instance into the get_model function. This might only be suitable for non-flask apps that use a single thread and session, but perhaps that is sufficient. Hope that helps, Simon -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.