On Wednesday, August 22, 2012 3:12:02 PM UTC+1, Simon King wrote:
>
> On Wed, Aug 22, 2012 at 2:44 PM, David McKeone 
> <davidm...@gmail.com<javascript:>> 
> 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 <javascript:>') 
>     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 
>


Yes, that solution seems to be the only way to do it.  Use the 
flask-SQLAlchemy models and include a 'fake' flask session when doing 
something outside of flask.  I had thought about asking on the Flask forum, 
but then it seemed like it might be too specific to the way that SQLAlchemy 
worked. 

Modifying it slightly though, I think you can just get away with using the 
app and the context manager:

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__':
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
    db = SQLAlchemy(app) 
    with app():
        db.create_all() 
        user =User('Joe', 'j...@example.com')
 
        print User.query.all()

-- 
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/-/-M1WncwtqT0J.
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.

Reply via email to