mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-31 04:48:02 -04:00
5ab558004c
such that the Session, cache manager, declarative_base are part of environment, and custom cache code is portable and now within "caching_query.py". This allows the example to be easier to "drop in" to existing projects.
80 lines
3.0 KiB
Python
80 lines
3.0 KiB
Python
"""advanced.py
|
|
|
|
Illustrate usage of Query combined with the FromCache option,
|
|
including front-end loading, cache invalidation, namespace techniques
|
|
and collection caching.
|
|
|
|
"""
|
|
|
|
from environment import Session
|
|
from model import Person, Address, cache_address_bits
|
|
from caching_query import FromCache, RelationshipCache
|
|
from sqlalchemy.orm import joinedload
|
|
|
|
def load_name_range(start, end, invalidate=False):
|
|
"""Load Person objects on a range of names.
|
|
|
|
start/end are integers, range is then
|
|
"person <start>" - "person <end>".
|
|
|
|
The cache option we set up is called "name_range", indicating
|
|
a range of names for the Person class.
|
|
|
|
The `Person.addresses` collections are also cached. Its basically
|
|
another level of tuning here, as that particular cache option
|
|
can be transparently replaced with joinedload(Person.addresses).
|
|
The effect is that each Person and his/her Address collection
|
|
is cached either together or separately, affecting the kind of
|
|
SQL that emits for unloaded Person objects as well as the distribution
|
|
of data within the cache.
|
|
"""
|
|
q = Session.query(Person).\
|
|
filter(Person.name.between("person %.2d" % start, "person %.2d" % end)).\
|
|
options(cache_address_bits).\
|
|
options(FromCache("default", "name_range"))
|
|
|
|
# have the "addresses" collection cached separately
|
|
# each lazyload of Person.addresses loads from cache.
|
|
q = q.options(RelationshipCache("default", "by_person", Person.addresses))
|
|
|
|
# alternatively, eagerly load the "addresses" collection, so that they'd
|
|
# be cached together. This issues a bigger SQL statement and caches
|
|
# a single, larger value in the cache per person rather than two
|
|
# separate ones.
|
|
#q = q.options(joinedload(Person.addresses))
|
|
|
|
# if requested, invalidate the cache on current criterion.
|
|
if invalidate:
|
|
q.invalidate()
|
|
|
|
return q.all()
|
|
|
|
print "two through twelve, possibly from cache:\n"
|
|
print ", ".join([p.name for p in load_name_range(2, 12)])
|
|
|
|
print "\ntwenty five through forty, possibly from cache:\n"
|
|
print ", ".join([p.name for p in load_name_range(25, 40)])
|
|
|
|
# loading them again, no SQL is emitted
|
|
print "\ntwo through twelve, from the cache:\n"
|
|
print ", ".join([p.name for p in load_name_range(2, 12)])
|
|
|
|
# but with invalidate, they are
|
|
print "\ntwenty five through forty, invalidate first:\n"
|
|
print ", ".join([p.name for p in load_name_range(25, 40, True)])
|
|
|
|
# illustrate the address loading from either cache/already
|
|
# on the Person
|
|
print "\n\nPeople plus addresses, two through twelve, addresses possibly from cache"
|
|
for p in load_name_range(2, 12):
|
|
print p.format_full()
|
|
|
|
# illustrate the address loading from either cache/already
|
|
# on the Person
|
|
print "\n\nPeople plus addresses, two through twelve, addresses from cache"
|
|
for p in load_name_range(2, 12):
|
|
print p.format_full()
|
|
|
|
print "\n\nIf this was the first run of advanced.py, try "\
|
|
"a second run. Only one SQL statement will be emitted."
|