Hi All,

I am using Flask-SQLAlchemy on a legacy database.  My SQLA classes / tables 
are setup using declarative base and autoload.  In addition to using the 
class to access persisted data, I also use plain old Python to enrich them 
with ephemeral data. 

Every time I load a User object, I'd like the instance for that particular 
object / row to retain its plain old python instance data.

My understanding is that Flask-SQLAlchemy will by default use a separate 
scoped_session for each request.  And that means at the end of the request 
session and user will go out of scope.  So in the next request to 
/users/Bob will instantiate a new User object whose will be reinitialized . 
. . each time I make this request I will be told it was "asked 1 time". 

Alternately, if I call /users_alt/Bob, then second time I call a 
DetachedInstanceError will be raised when I attempt to read user.owners.

I suspect there's a pattern used to accomplish what I want to do, but I 
have not tried the right Google search.  Any recommendations on how to 
approach this or searches to try / doc sections to read?   The state I'm 
storing in times_name_read_since_launch is actually complex enough that I 
don't want to persist it and have to keep that dependent state synchronized.

Alternately is there a way for me to reattach a SQLA object to the current 
requests' session?  Then, ideally, I could get updates from the database to 
User or Owner  objects, but retain my ephemeral state in the plain old 
python.  

Thanks for the help,
Rob

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData
from sqlalchemy import orm

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = connection_string
db = SQLAlchemy(app)


class Owner(db.Model):
    __table__ = db.Table('Owners', MetaData(), autoload=True, autoload_with=
db.engine)


class User(db.Model):
    __table__ = db.Table('users', MetaData(), autoload=True, autoload_with=
db.engine)
    owners = db.relationship('Owner', primaryjoin=
"foreign(User.userId)==remote(Owner.userId)", uselist=True,
                             backref=db.backref('user', uselist=False))

    users_seen = dict()

    @orm.reconstructor
    def init_on_load(self):
        self.times_name_read_since_launch = 0

    @classmethod
    def lookup_by_name(cls, name):
        user_ = User.users_seen.get(name)
        if user_ is None:
            user_ = User.query.filter(User.UserName == name).one()
        return user_

    @classmethod
    def store_by_name(cls, user_):
        if user_.UserName not in User.users_seen:
            User.users_seen[user_.UserName] = user_

    @property
    def name(self):
        self.times_name_read_since_launch += 1
        return self.UserName


@app.route("/users/<string:name>")
def user(name):
    user_ = User.query.filter(User.UserName == name).one()
    return "{} with {} - asked {} times".format(user_.name, user_.owners, 
user_.times_name_read_since_launch)


@app.route("/users_alt/<string:name>")
def user_alt(name):
    user_ = User.lookup_by_name(name)
    User.store_by_name(user_)
    owners = None
    if user_.times_name_read_since_launch > 0:
        # don't lazy load addresses the first request, simulates more 
complex actual behavior desired
        owners = user_.owners
    return "{} with {} - asked {} times".format(user_.name, owners, user_.
times_name_read_since_launch)


db.create_all()


-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/66717a53-d81b-4cce-be68-601c5d673284%40googlegroups.com.

Reply via email to