I’ve been using SQLAlchemy to connect to a MySQL database. It has been working good up to now, but I’ve run into some trouble. I wanted to call a method on one of my classes after it was queried which would assign a few new variables. The trouble was that only a single user per query would end up having the variables set by my ‘on_query’ method.
...stuff setting up a connection to the database as well as a SQL session.
All were done using default values.
class UserTest(Base):
__tablename__ = "testtable"
ID = Column(Integer(unsigned=True),
primary_key=True, nullable=False, autoincrement=True)
def __init__(self):
pass
def on_query(self):
self.foo = "bar"
query = session.query(UserTest)
for u in query:
u.on_query()
print [hasattr(u, "foo") for u in query]
#prints [False, False, False, False, False, False, False, False, False, True]
session.close()
I discovered that if I were to create a list by iterating the query, the ‘on_query’ method would work as I intended it to.
users = [u for u in query]
for u in users:
u.on_query()
print [hasattr(u, "foo") for u in users]
#prints [True, True, True, True, True, True, True, True, True, True]
What is the cause of this? And is there a way to stop it from removing the ‘foo’ variable each iteration? I’d prefer to keep the Users inside of the query object if possible.
In the first case, the query is actually spawned twice, once by the for-loop, and once by the print statement.
Since the for-loop keeps replacing the
ureference, at the end of the loop, only the last one remains in SQLAlchemy session. You can verify this withprint session.identity_map.When the query is spawned for the second time by the print statement, all except the last one has to be retrieved from the database again, while the last one is retrieved directly from SQLAlchemy session, thus having the
fooattribute set.EDIT: One way to do this more transparently is by using reconstructor, e.g.