On Thursday, August 23, 2012 3:01:50 AM UTC+1, Michael Bayer wrote: > > > On Aug 22, 2012, at 5:33 PM, David McKeone wrote: > > > I suppose I should be more clear. This is really a long term question, > I was just looking for some kind of answer now because I don't want to code > myself into a corner in the short term. Currently I can make requests > outside of a flask request context by using the app.test_request_context() > context manager, and it seems to do the right thing. > > > > In the long term I'm looking for 2 (maybe 3) things that I already get > from Flask-SQLAlchemy: > > 1) Session teardown for every request (looks like that is done with a > call to session.remove() in the request teardown) > > you can use the Session provided by flask-sqlalchemy, which has the nice > quality that it aligns itself with the current request. > > He can make that feature more open-ended though. I should be able to say > flask_sqlalchemy.request_scope(some_sessionmaker) to set that up with any > sessionmaker of my choosing. > > > > 2) Debug query tracking for use with Flask-DebugToolbar (Plus > compatibility with other plug-ins that may expect Flask-SQLAlchemy) > > the logic i see in flask-sqlalchemy related to debug tracking has no > connection to the "db.Model" class at all. its just some connection > events which are ultimately established via the "SQLAlchemy" class. Your > existing non-flask SQLA models will participate in the Session/Engine used > by Flask without impacting this functionaltiy. > > > > 3) The Model.query behaviour (it's nice, but I could live without it, > since its really just syntactic) > > scoped_session has a query_property available, so you can pull that from > Flask's scoped_session using SQLAlchemy public APIs like this: > > sa = SQLAlchemy(db) > > # API: > http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#sqlalchemy.orm.scoping.ScopedSession.query_property > > Base.query = sa.session.query_property > > > or to get exactly flask's, which appears to add three methods get_or_404, > first_or_404, paginate: > > Base.query = flask_sqlalchemy._QueryProperty(sa) > > > > > > > Didn't say this explicitly; for now I will do what you say and forge > ahead with things. I think I see the path, but I'll make sure to let you > (the list) know if I run into trouble. > > good luck ! >
Slugged it out today and got this working, hooray! Thanks again for your help Mike (and for the time you probably put in to parse the Flask-SQLAlchemy code). If you are at PyCon this year I WILL find you and I WILL buy you beer, unless you don't drink, in which case I WILL buy you soda or coffee. I haven't done the Base.query part, and I may never do it (more below), but everything else works great and all my tests pass after switching to the new method. The more I use the new system the more I wish I would have started with it. Perhaps I can get it documented as an option, because I find it makes it far more clear where the models belong in the grand scheme of things. Now, not everyone has 93 tables, a boat-load of relationships and requirements for doing things outside of HTTP like I do, so I can understand why it's been done the way that it's been done, but having to pass the db instance into all of my model definitions (and the resulting project structure issues I had) just wasn't worth it. I've also found that having to use the session directly makes it far more clear which session is being used, and how. Not to mention the benefits from being able to decouple my models from Flask completely. So, in the name of Google search completeness, here is the solution that I ultimately ended up with, adapted for the simple User model from above, for those like me who want/need it. (It's quite simple, and I'm amazed that it hadn't occurred to me to try it like this) from flask import Flask from flask_sqlalchemy import SQLAlchemy from sqlalchemy import Column, Integer, String from sqlalchemy.ext.declarative import declarative_base app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app) Base = declarative_base() 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) @app.before_first_request def setup(): # Recreate database each time for demo Base.metadata.drop_all(bind=db.engine) Base.metadata.create_all(bind=db.engine) db.session.add(User('Bob Jones', 'b...@gmail.com')) db.session.add(User('Joe Quimby', 'e...@joes.com')) db.session.commit() @app.route('/') def root(): users = db.session.query(User).all() return u"<br>".join([u"{0}: {1}".format(user.name, user.email) for user in users]) if __name__ == '__main__': app.run('127.0.0.1', 5000) -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/3nDcblYbMQYJ. 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.