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.

Reply via email to