Django có 4 level cache, đi từ thô-rộng đến mịn-hẹp.
Per-site cache (cặp UpdateCacheMiddleware + FetchFromCacheMiddleware) cache toàn bộ page response — hợp với site mostly-read như blog, landing. Per-view cache (decorator @cache_page(60 * 15) hoặc cache_page() ở URLconf) chỉ cache một view cụ thể. Template fragment ({% load cache %}{% cache 300 sidebar request.user.id %}...{% endcache %}) cache một phần của template. Low-level cache API (cache.get / cache.set) cache object/queryset bất kỳ — linh hoạt nhất.
from django.core.cache import cache
def top_posts():
key = 'top_posts:v2'
posts = cache.get(key)
if posts is None:
posts = list(Post.objects.popular()[:10])
cache.set(key, posts, timeout=300)
return postsBackend production thường là Redis (django.core.cache.backends.redis.RedisCache từ Django 4.0+).
Vấn đề khó nhất của cache luôn là invalidation — khi nào xoá key cũ? Hai pattern thường dùng: gắn signal post_save để cache.delete(), hoặc thêm version suffix vào key (top_posts:v2) rồi tăng version khi schema/format thay đổi. Tránh TTL quá dài (1 ngày) cho dữ liệu mutable, vì user sẽ thấy giá trị cũ trong nhiều giờ liền.
Django offers four cache levels, from coarse-wide to fine-narrow:
- Per-site cache —
UpdateCacheMiddleware+FetchFromCacheMiddlewarecache the whole page response. Fits mostly-read sites like blogs/landing pages. - Per-view cache —
@cache_page(60 * 15)decorator orcache_page()on the URL. Caches one specific view. - Template fragment —
{% load cache %}{% cache 300 sidebar request.user.id %}...{% endcache %}. Caches a piece of the template. - Low-level cache API —
cache.get/cache.setfor any object/queryset. The most flexible.
from django.core.cache import cache
def top_posts():
key = 'top_posts:v2'
posts = cache.get(key)
if posts is None:
posts = list(Post.objects.popular()[:10])
cache.set(key, posts, timeout=300)
return postsThe usual production backend is Redis (django.core.cache.backends.redis.RedisCache since Django 4.0+).
Pitfall: The hardest problem is cache invalidation — when to drop the old key? Safe patterns: hook signal post_save to call cache.delete(), or add a version suffix to the key (top_posts:v2) and bump it when schema/format changes. Avoid very long TTLs (1 day) on mutable data — users will see stale results.