Django Caching Patterns

Django Caching Patterns

Explore django caching patterns code snippets and tutorials

Django Caching Patterns

Caching in Django in practice: Redis backend, cache_page and template fragments

How do you set up caching in Django in practice?

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# ======================================================================
# Q: How do you set up caching in Django in practice?
# ======================================================================

# settings.py (Django 4.0+ has a native Redis backend)
CACHES = {'default': {
    'BACKEND': 'django.core.cache.backends.redis.RedisCache',
    'LOCATION': 'redis://redis:6379/1',
    'KEY_PREFIX': 'shop', 'TIMEOUT': 300}}

@cache_page(60 * 5)                         # whole page
@vary_on_headers('Accept-Language')
def category(request, slug): ...

{% load cache %}                            {# template fragment #}
{% cache 600 sidebar request.user.id %} ... {% endcache %}
Django Caching Patterns

Cache eviction algorithms and implementing an LRU cache in Python

In Redis this is configured with maxmemory-policy (allkeys-lru, allkeys-lfu, volatile-ttl...).

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ======================================================================
# Q: What are cache eviction algorithms, and how do you implement an LRU cache
# in Python?
#
# In Redis this is configured with maxmemory-policy (allkeys-lru, allkeys-lfu,
# volatile-ttl...). A classic question is to implement an LRU cache in Python:
# ======================================================================

from collections import OrderedDict

class LRUCache:
    def __init__(self, capacity):
        self.capacity, self.data = capacity, OrderedDict()
    def get(self, key):
        if key not in self.data:
            return None
        self.data.move_to_end(key)          # most recently used
        return self.data[key]
    def put(self, key, value):
        self.data[key] = value
        self.data.move_to_end(key)
        if len(self.data) > self.capacity:
            self.data.popitem(last=False)    # evict the least recently used
Django Caching Patterns

Cache-aside (lazy loading) in Django with invalidation on commit

What is the cache-aside (lazy loading) pattern, the most common caching pattern?

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# ======================================================================
# Q: What is the cache-aside (lazy loading) pattern, the most common caching
# pattern?
# ======================================================================

def get_product(pk):
    key = f'product:v2:{pk}'
    data = cache.get(key)
    if data is None:                                   # cache miss
        data = ProductSerializer(Product.objects.get(pk=pk)).data
        cache.set(key, data, timeout=60 * 15)
    return data

# invalidation when it changes
def update_product(product):
    product.save()
    transaction.on_commit(lambda: cache.delete(f'product:v2:{product.pk}'))