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.