The Per-View Cache

A more granular way to use the caching framework is by caching the output of individual views. django.views.decorators.cache defines a cache_page decorator that will automatically cache the view’s response for you. It’s easy to use:

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request):

cache_page takes a single argument: the cache timeout, in seconds. In the above example, the result of the my_view() view will be cached for 15 minutes. (Note that I’ve written it as 60 * 15 for the purpose of readability. 60 * 15 will be evaluated to 900 – that is, 15 minutes multiplied by 60 seconds per minute.)

The per-view cache, like the per-site cache, is keyed off of the URL. If multiple URLs point at the same view, each URL will be cached separately. Continuing the my_view
example, if your URLconf looks like this:

urlpatterns = [
url(r’^foo/([0-9]{1,2})/$’, my_view),
]

then requests to /foo/1/ and /foo/23/ will be cached separately, as you may expect. But once a particular URL (e.g., /foo/23/) has been requested, subsequent requests to that URL will use the cache.

cache_page can also take an optional keyword argument, cache, which directs the decorator to use a specific cache (from your CACHES setting) when caching view results.

By default, the default cache will be used, but you can specify any cache you want:

@cache_page(60 * 15, cache=”special_cache”)
def my_view(request):

You can also override the cache prefix on a per-view basis. cache_page takes an optional keyword argument, key_prefix, which works in the same way as the CACHE_MIDDLEWARE_KEY_PREFIX setting for the middleware. It can be used like this:

@cache_page(60 * 15, key_prefix=”site1″)
def my_view(request):

The key_prefix and cache arguments may be specified together. The key_prefix argument and the KEY_PREFIX specified under CACHES will be concatenated.

Specifying Per-View Cache in the Urlconf

The examples in the previous section have hard-coded the fact that the view is cached, because cache_page alters the my_view function in place. This approach couples your view to the cache system, which is not ideal for several reasons. For instance, you might want to reuse the view functions on another, cache-less site, or you might want to distribute the views to people who might want to use them without being cached.

The solution to these problems is to specify the per-view cache in the URLconf rather than next to the view functions themselves. Doing so is easy: simply wrap the view function with cache_page when you refer to it in the URLconf.

Here’s the old URLconf from earlier:

urlpatterns = [
url(r’^foo/([0-9]{1,2})/$’, my_view),
] Here’s the same thing, with my_view wrapped in cache_page:
from django.views.decorators.cache import cache_page

urlpatterns = [
url(r’^foo/([0-9]{1,2})/$’, cache_page(60 * 15)(my_view)),
]

Template Fragment Caching

If you’re after even more control, you can also cache template fragments using the cache template tag. To give your template access to this tag, put {% load cache %} near the top of your template. The {% cache %} template tag caches the contents of the block for a given amount of time.

It takes at least two arguments: the cache timeout, in seconds, and the name to give the cache fragment. The name will be taken as is, do not use a variable.

For example:
{% load cache %}
{% cache 500 sidebar %}
.. sidebar ..
{% endcache %}

Sometimes you might want to cache multiple copies of a fragment depending on some dynamic data that appears inside the fragment.

For example, you might want a separate cached copy of the sidebar used in the previous example for every user of your site. Do this by passing additional arguments to the {% cache %} template tag to uniquely identify the cache fragment:
{% load cache %}
{% cache 500 sidebar request.user.username %}
.. sidebar for logged in user ..
{% endcache %}

It’s perfectly fine to specify more than one argument to identify the fragment. Simply pass as many arguments to {% cache %} as you need. If USE_I18N is set to True the per-site middleware cache will respect the active language.

For the cache template tag you could use one of the translation-specific variables available in templates to achieve the same result:

{% load i18n %}
{% load cache %}

{% get_current_language as LANGUAGE_CODE %}

{% cache 600 welcome LANGUAGE_CODE %}
{% trans “Welcome to example.com” %}
{% endcache %}

The cache timeout can be a template variable, as long as the template variable resolves to an integer value.

For example, if the template variable my_timeout is set to the value 600, then the following two examples are equivalent:
{% cache 600 sidebar %} … {% endcache %}
{% cache my_timeout sidebar %} … {% endcache %}

This feature is useful in avoiding repetition in templates. You can set the timeout in a variable, in one place, and just reuse that value. By default, the cache tag will try to use the cache called template_fragments. If no such cache exists, it will fall back to using the default cache. You may select an alternate cache backend to use with the using keyword argument, which must be the last argument to the tag.

{% cache 300 local-thing … using=”localcache” %}

It is considered an error to specify a cache name that is not configured.

If you want to obtain the cache key used for a cached fragment, you can use make_template_fragment_key. fragment_name is the same as second argument to the cache template tag; vary_on is a list of all additional arguments passed to the tag. This function can be useful for invalidating or overwriting a cached item, for example:

>>> from django.core.cache import cache
>>> from django.core.cache.utils import make_template_fragment_key
# cache key for {% cache 500 sidebar username %}
>>> key = make_template_fragment_key(‘sidebar’, [username])
>>> cache.delete(key) # invalidates cached template fragment

Back to Tutorial

Share this post
[social_warfare]
JMXAccessorQueryTask: query MBean Ant task
The Low-Level Cache API

Get industry recognized certification – Contact us

keyboard_arrow_up