How to remember results from querying SQLAlchemy relations (to implement caching)?
Suppose I have a mapped class Article
. It has a rel开发者_高级运维ation category
that does a query each time I access it (article.category
would issue a query to get the category
or article
).
How do I proxy the article.category
call so that the result is queried from the database, then remembered and then returned?
Thanks, Boda Cydo.
Does SA really issue a query every time you access the relation in the same session? IMO, it should not happen, as the result should get cached automatically within the session.
In order to check that no SQL
is issued, just turn on logging and see for yourself:
metadata.bind.echo = 'debug'
c = session.query(Child).first() # issues SELECT on your child table(s)
print "child: ", c
print "c.parent: ", c.parent # issues SELECT on your parent table, then prints
print "c.parent: ", c.parent # just prints (no SQL)
print "c.parent: ", c.parent # just prints (no SQL)
Shall your code work otherwise by default, please provide code snippet.
In case you really just need to cache the result, see below (very similar solution to another question you posted):
class MyChild(Base):
__tablename__ = 'MyChild'
id = Column(Integer, primary_key=True)
parent = relation('Parent')
# ... other mapped properties
def __init__(self):
_parent_cached = None
@property
def parent_cached(self):
if self._parent_cached is None:
self._parent_cached = self.parent
But in order to have the result when your object is detached from the session you must call this property before detaching. (Also it does not handle situation when the parent
is None
. Do you always have parent?).
The option with eager load is simplier and once you load the object, you should have the relation loaded already (key is to have lazy=False
):
class MyChild(Base):
__tablename__ = 'MyChild'
id = Column(Integer, primary_key=True)
parent = relation('Parent', lazy=False)
# ... other mapped properties
...
精彩评论