In the Python world, Django is the de facto standard choice as the most popular rich MVC/MVP framework around. It has a fantastic caching framework as well.
Django comes with a robust caching framework that lets you save dynamic pages so they don't have to be calculated for each request. Not only that, but also Django offers an abstract caching API that hides the specific implementation of the caching backend and offers a clean API to cache whatever you feel right, whenever you want to.
We are assuming you are a seasoned Django developer with some experience building Django applications in this recipe. Our goal here is to configure Django to use memcached as a caching backend and to introduce you to some of the features of Django's caching framework.
You will need to have a simple Django application to play with, if you don't have one you can create an empty project with an empty application by using the following:
django-admin.py startproject djangocache cd djangocache/ python manage.py startapp cachista python manage.py runserver
This will create a project called djangocache
and a simple app (module) inside your project that we called cachista
.
If you don't have python-memcached installed already, you can simply use pip
for that:
pip install python-memcached
Let's start by editing the
settings.py
file in your Django project (djangocache/settings.py
, in our case), we will be using python-memcached for this recipe (you can usepylibmc
too if you like).The caching configuration parameter is controlled by the
CACHES
variable in the settings file. By default, you will not find this variable in yoursettings.py
file, so we will need to add to it theBACKEND
key in the'default'
dict which indicates the memcached client that you are planning to use.CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } }
In this example, we used
MemcachedCache
which uses the python-memcached library.If you are planning to use the faster
pylibmc
, you will need to replace this withdjango.core.cache.backends.memcached.PyLibMCCache
.The
LOCATION
key in the'default'
dict is where your memcached server is located, if you have a memcached cluster, you can change the value to be a list as follows:CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': [ 'cache-1.example.com:11211', 'cache-2.example.com:11211', ] } }
It's very important to understand that if you are planning to use multiple Django servers as a cluster, all the configurations of those servers need to have the same order as this caching list.
Now, let's tell Django to cache one of our views, it will automatically cache the view response for us. You will need to import that cache_page decorator
first from django.views.decorators.cache import cache_page
.
@cache_page(60 * 15, key_prefix="site1") def my_view(request): """ my view code goes here """
Piece of cake! We told Django to cache this view for 15
minutes and the key prefix in the cache store will be "site1"
.
Now, do you remember the "default" we wrote in our CACHES
setting? That was to setup multiple caching backends for Django! Yes, you can cache certain pages on certain caching backends. You can specify the caching backend in your cache_page
view.
@cache_page(60 * 15, cache="memory_cache")
The "memory_cache"
value must correspond to a key in your CACHES
setting where you specify the caching backend settings. Fantastic!
As in Rails, you can specify fragments of your template to be cached.
{% load cache %} {% cache 500 sidebar %} .. sidebar .. {% endcache %}
Now, let's use the caching API to do manual caching of a value in our action/controller code from the following:
django.core.cache import get_cache cache = get_cache('default') cache.set('key', 'Hello Memcached!', 15) print cache.get('key')
This looks very similar to the direct memcached API but it's not! It's an abstract API that can actually use multiple backends for you; memcached is one of them as configured in the CACHES
setting.
We started by defining the CACHES
variable in the settings.py
file and there we can define multiple cache regions with different backends. Django supports multiple cache backends, file-based, memory-based, and database-based. In our case, we used python-memcached backend and we specified that for the 'default'
cache region.
Of course, it's very popular to use memcached as a cluster and to specify the list of servers to your configuration.
You can also specify some interesting options along with the LOCATION
and BACKEND
keys, some examples of the same are as follows:
TIMEOUT
: The default timeout, in seconds, to use for the cache. The default value is 300 seconds (5 minutes)KEY_PREFIX
: A string that automatically will be prefixed to all cache keys.
Then we played with cache_page decorator
which automatically caches a view for us, you can specify the prefix or the cache region you are planning to use for this particular page.
Then we have seen the template caching, you can cache pieces/fragments of your template code with the "cache"
tag, you can specify in the identifier for this cached fragment and expiration.
In our case we used the sidebar
identifier as stated in the following line:
{% cache 500 sidebar %}
The expiration is set to 500
seconds, but interestingly you can specify more keywords for your identifier for the same fragment.
{% cache 500 sidebar welcome %}
Also, you can use the low-level caching API if you want more granular control over your caching and that was described in the last code snippet.