Jimmy Page is a simple caching app for Django, inspired by Johnny Cache, but for whole pages rather than querysets. It is an automatic generation-based page cache.
If Johnny Cache (generational caching of querysets) is the first line of defense in caching, Jimmy Page is the last: it caches the output of views forever, but with conservative expiration on database writes. Jimmy uses a global "generation" number as part of the cache key, which is incremented whenever any model is saved or deleted, expiring the whole page cache. This technique is similar to that described by Open Logic from the Rails community.
This technique provides easy whole-page caching, with an assurance that no part of the site will ever contain stale content. The conservative approach to expiration allows Jimmy to function in a drop-in manner, without any domain-specific knowledge of how data updates might affect the output of views. It will greatly speed up slowly updated sites, especially when used in combination with Johnny Cache and carefully designed, more aggressive caching for particularly intensive views. This technique is not likely to be effective in sites that have a high ratio of database writes to reads.
This is the first, as yet largely untested alpha release. Some notes:
- In order to function properly, Johnny Cache should be installed and used. Johnny Cache patches the Django caching framework to allow caching with infinite timeouts, something that this app does not provide alone. If you don't want to use Johnny Cache, you should set the JIMMY_PAGE_CACHE_SECONDS setting to something other than 0.
- If you have any custom SQL that updates the database without emitting post_save or pre_delete signals, things might get screwy. At this stage, Jimmy Page works best with sites using vanilla ORM calls.
Install using pip:
pip install -e git://github.com/yourcelf/django-jimmypage.git#egg=django-jimmypage
or clone the git archive and use setup.py:
python setup.py install
To use, include jimmypage in your INSTALLED_APPS setting, and define JIMMY_PAGE_CACHE_PREFIX in your settings.py file:
# settings.py INSTALLED_APPS = ( ... "jimmypage", ... ) JIMMY_PAGE_CACHE_PREFIX = "jp_mysite"
To cache a view, use the cache_page decorator:
from jimmypage.cache import cache_page @cache_page def myview(request): ...
Any update to any table will clear the cache (by incrementing the generation), unless the tables are included in the JIMMY_PAGE_EXPIRATION_WHITELIST. The defaults can be overridden by defining it in your settings.py. By default it includes:
JIMMY_PAGE_EXPIRATION_WHITELIST = [ "django_session", "django_admin_log", "registration_registrationprofile", "auth_message", "auth_user", ]
Views are cached on a per-user, per-language, per-path basis. Anonymous users share a cache, but authenticated users get a separate cache, ensuring that no user will ever see another's user-specific content. The cache is only used if:
- The request method is GET
- There are no messages stored for the request
- The response status is 200
- The response does not contain a Pragma: no-cache header
Please contribute any bugs or improvements to help make this better!
Current TODOs include:
- Much more testing, analysis, and code review
- middleware to apply the caching to everything, and a decorator to exclude particular views
- Hooks into Django Debug Toolbar to make debugging easier