Package: django-cachetree
django-cachetreeprovides caching of configurable trees of related model
instances in Django. For example, withdjango-cachetreeyou could easily
cache a user instance and the user’s photos and comments on a photo-sharing
site as a single item in the cache. When a user is fetched from the database,
its related objects are “prefetched” before the user object is set in the
cache. This means that when you retrieve the user object from the cache, the
related objects are there with it and you can access them without hitting the
database (or hitting the cache again):user = User.objects.get_cached(pk=1) # user not yet in cache, hits the
                                     # database and prefetches related objects

....

user = User.objects.get_cached(pk=1) # hits the cache
photos = user.photo_set.all()
print photos[0].title # doesn't hit database or cache
comments = user.comment_set.all()
print comments[0].date # doesn't hit database or cacheYou can configuredjango-cachetreeto cache related objects of related
objects of related objects, to any depth. For example, on a blog, you could
cache author objects along with their set of blog entries, the set of comments
for each of those entries, and the commenter for each of those comments.django-cachetreeautomatically invalidates cached objects when they or the
related objects cached with them are changed, deleted, or created.Requirementsdjango-cachetreerequires Django 1.3 and Python 2.5, 2.6, or 2.7.InstallationYou can installdjango-cachetreewithpip install django-cachetreeoreasy_install django-cachetreeThis will addcachetreeto your Python path. Add'cachetree'to yourINSTALLED_APPS, and add'cachetree.middleware.InstallCachetree'to your middleware classes. This will add aget_cachedmethod to
the default manager for each of your cached models. (Note that becauseget_cachedis added to the manager class, it will be available on all
instances of that manager class. However, attempting to use it on a model not defined in yourCACHETREEsetting will raise aValueError.) If
invalidation is enabled,cachetree.install()also registers signal
handlers that are used for invalidation.Installingcachetreevia middleware will only work if there is a page request to trigger the middleware. To install and usecachetreeoutside of a request-response context (for example, in a test suite), runcachetree.install()in your testrunner or at the bottom of your models file.TheCACHETREEsettingTo usedjango-cachetree, add aCACHETREEsetting tosettings.py.
TheCACHETREEsetting consists of nested dictionaries that telldjango-cachetreewhat to cache. The keys in the topmost dictionary should
contain theapp_labelfor each app that has models you wish to cache. Eachapp_label’s dictionary should contain a key with the class name (as a
string) for each cached model in the app. These are the models whose managers
will provide aget_cachedmethod, and are known as “root models” indjango-cachetree’s terminology. For example, to cacheAuthorandEntrymodels but none of their related objects in an app calledmyapp,
you would write:CACHETREE = {
    "myapp": {
        "Author": {},
        "Entry": {},
    }
}The dictionary for each root model can contain three optional keys,"timeout","lookups", and"prefetch".timeoutThe timeout, in seconds, to use when caching instances of this model.
Overrides your global timeout setting inCACHES.lookupsA tuple containing the field names that can be used as kwargs when callingget_cachedfor this model. By default, lookups are allowed by primary
key. If your model’s primary key field isid, the default setting
would be("pk", "id").To lookup by a combination of fields, include the field names as a tuple
within yourlookupstuple. For example, to look upUserinstances
byidor byfirst_nameandlast_name:CACHETREE = {
    "auth": {
        "User": {
            "lookups": (
                "id",
                ("first_name", "last_name"),
            )
        }
    }
}If invalidation is enabled, lookups are restricted to fields defined on
the model, includingForeignKeyfields andOneToOneFields but
excludingManyToManyFields. SpecifyingManyToManyFields or
reverseForeignKeyorOneToOneFields will raisecachetree.ImproperlyConfigured. Lookup separators (for example,username__contains) are also not allowed and will raiseImproperlyConfigured. To know what keys to invalidate,django-cachetreerequires exact lookups (which is the default when no
lookup separator is used).prefetchA dictionary specifying the tree of related objects to prefetch and cache
with the root model instance. Each key should be the attribute name (as a
string) of the related instance(s) to be prefetched. Each key’s value
should be a dictionary of attribute names to prefetch on the related
instance(s), or an empty dictionary (orNone) if no further
relationships should be prefetched. Any relationship can be prefetched:OneToOneField,ForeignKey, andManyToManyField, forward or
reverse. For example, to cache author objects, their set of entries, those
entries’ comments, and each comment’s commenter, you might write:CACHETREE = {
    "myapp": {
        "Author": {
            "lookups": (
                "pk",
                "id",
                ("first_name", "last_name"),
            ),
            "prefetch": {
                "entry_set": {
                    "comment_set": {
                        "commenter": {},
                    },
                },
            },
        },
    },
}The above example assumes that eachAuthorobject is related to its
entries by anentry_setattribute, each entry object is related to its
comments by acomment_setattribute, and each comment object relates
to its commenter by acommenterfield.If invalidation is enabled, there is one restriction on prefetching. If
you prefetch aManyToManyField(forward or reverse) that defines a
custom intermediary model (as specified with thethroughargument on
the model field definition), you must also prefetch the attribute that
points to the intermediary instances. For example, if you have anEntrymodel related to aCategorymodel through a custom
intermediary model calledEntryCategory, and you prefetchEntry.categories(aManyToManyField), you must also prefetch theEntry.entrycategory_setattribute that Django adds to yourEntrymodel, orImproperlyConfiguredwill be raised.You can find exampleCACHETREEsettings indjango-cachetree’s test
module, which defines models and settings covering all possible relationships.PrefetchingManyToManyFields and ReverseForeignKeysWhen you configuredjango-cachetreeto cache aManyToManyFieldor
reverseForeignKey, such asuser.photo_set(wherePhotohas a
foreign key toUser),django-cachetreecallsuser.photo_set.all(),
evaluates the queryset, and caches the results on theuserwhen
prefetching. Subsequent calls touser.photo_set.all()will return the
cached results, rather than returning a new queryset (which would require
hitting the database again to evaluate).django-cachetreepatches the manager onManyToManyFieldandForeignKeydescriptors to make this behavior
possible. However, only theall()method is patched. If you calluser.photo_set.count()oruser.photo_set.filter()or any other method
besidesall(), you will bypass the cached results and hit the database.
Assuming your object set is not huge, you can avoid hitting the database by
callingall()and counting or filtering the results within your code.How Invalidation WorksWhen you callcachetree.install(),django-cachetreeanalyzes yourCACHETREEsetting and determines which relationships must be followed in
order to traverse the tree backwards from prefetched related instances to
their root model instances. Using this information, whenever a model defined
in yourCACHETREEsetting (either as a root model or as a prefetched
relationship) is created, saved, or deleted (and in the case ofManyToManyFields and reverseForeignKeys, added, removed, or cleared
using the field manager’sadd(),remove(), orclear()methods),django-cachetreetraverses its relationships back to the root model
instance(s) that need to be invalidated.django-cachetreeuses apost_initsignal handler to keep track of each instance’s initial state,
and when the instance changes and is saved,django-cachetreefollows both
the instance’s new and initial values to find the root model instances that
need to be invalidated. For example, if you cacheAuthorobjects along
with theirentry_set, and you change anEntryobject’s author,django-cachetreewill invalidate both the new and the initialAuthorobjects for that entry.Important Caveat:django-cachetreedoes not perform invalidation when
you run anUPDATEquery using a manager’supdate()method. You will
either need to invalidate the affected instances yourself by callinginvalidate()(described below), rely on the cached objects to expire naturally,
or avoid usingupdate().Cachetree Authentication BackendIfdjango.contrib.authis installed in your project, you can usedjango-cachetree’s authentication backend:AUTHENTICATION_BACKENDS = (
    "cachetree.auth.CachedModelBackend",
)This will look in the cache before hitting the database when authenticating
users. Adding theauth.Usermodel to yourCACHETREEsetting is
optional. Not adding it implies the following settings:CACHETREE = {

        ...

        "auth": {
            "User": {
                "lookups":(
                    "pk",
                    "username",
                ),
            },
        },
    }If you wish to allow additional lookups onUseror to prefetch related
instances, explicitly defineUserin yourCACHETREEsetting.UtilsThe following functions can be imported fromcachetree:get_cached_object_or_404Works likeget_object_or_404, but usesget_cachedinstead ofget.invalidate(*instances)Traverses relationships on each of theinstancesto find and invalidate
its root model instance(s).no_invalidationDecorator that disables invalidation for the duration of the function it decorates.Additional SettingsCACHETREE_DISABLESet toTrueto disabledjango-cachetree. Calls toget_cached()orget_cached_object_or_404()will useget(). Calls toinvalidate()and uses of theno_invalidationdecorator will have
no effect. This allows you to temporarily disabledjango-cachetreewithout modifying any code. Default:False.CACHETREE_INVALIDATESet toFalseto disable invalidation.django-cachetreewill
continue to cache model objects but will not invalidate them when they
change. Calls toinvalidate()and uses of theno_invalidationdecorator will have no effect. Default:True.CACHETREE_MANY_RELATED_PREFIXControls the prefixdjango-cachetreeuses when it prefetches a set of
related objects and caches it on a model instance. In the example ofauthor.entry_set.all(),django-cachetreecaches the author’s set
of entries asauthor._cached_entry_set, and subsequent calls toauthor.entry_set.all()return this attribute. Normally you will not
need to access this attribute directly, but this setting allows you to
change the prefix in case of name conflicts. Default:_cached_.