Что такое кеширование шаблонов в Django?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Кеширование шаблонов в Django
Кеширование шаблонов в Django — это механизм оптимизации производительности, который заключается в кешировании (сохранении в памяти) результатов рендеринга HTML-шаблонов, чтобы избежать повторной обработки одних и тех же данных. Django предоставляет несколько подходов к кешированию на разных уровнях.
Типы кеширования в Django
1. Кеширование на уровне вью (View-level caching)
Кеширует весь результат представления:
from django.views.decorators.cache import cache_page
from django.shortcuts import render
from .models import Article
# Кеширует результат на 60 секунд
@cache_page(60)
def article_list(request):
articles = Article.objects.all()
return render(request, 'articles/list.html', {'articles': articles})
# Используется в urls.py
from django.urls import path
urlpatterns = [
path('articles/', cache_page(60)(article_list)),
]
2. Кеширование на уровне шаблона (Template-level caching)
Кеширует отдельные блоки шаблона:
{% load cache %}
<!-- Кешируем блок на 300 секунд с ключом 'sidebar' -->
{% cache 300 sidebar user.id %}
<div class="sidebar">
<h3>{{ user.name }} Профиль</h3>
<p>{{ user.bio }}</p>
</div>
{% endcache %}
<!-- Кешируем список статей -->
{% cache 600 article_list %}
<div class="articles">
{% for article in articles %}
<div class="article">
<h2>{{ article.title }}</h2>
<p>{{ article.content|truncatewords:50 }}</p>
</div>
{% endfor %}
</div>
{% endcache %}
3. Кеширование на уровне фрагмента (Fragment caching)
from django.core.cache import cache
from .models import Category
def product_list(request):
# Пытаемся получить из кеша
categories = cache.get('all_categories')
# Если не в кеше — получаем из БД и сохраняем
if categories is None:
categories = Category.objects.all()
cache.set('all_categories', categories, 3600) # На 1 час
return render(request, 'products/list.html', {'categories': categories})
Настройка кеша в Django
settings.py:
# Использование Redis (рекомендуется для production)
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'CONNECTION_POOL_KWARGS': {'max_connections': 50}
}
}
}
# Использование локального памяти (для разработки)
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
}
# Использование базы данных
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
}
}
# Использование файловой системы
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
Примеры работы с кешем
Базовые операции с cache API:
from django.core.cache import cache
# Установка значения в кеш
cache.set('user_profile:123', user_data, 3600) # Живёт 1 час
# Получение значения из кеша
user_data = cache.get('user_profile:123')
# Получение с значением по умолчанию
user_data = cache.get('user_profile:123', default={})
# Проверка наличия ключа
if cache.has_key('user_profile:123'):
print("Есть в кеше")
# Удаление из кеша
cache.delete('user_profile:123')
# Очистка всего кеша
cache.clear()
# Увеличение значения (если число)
cache.incr('page_views', 1)
# Установка если не существует
cache.add('lock_key', 'locked', 60) # Вернёт False если уже есть
Кеширование функций
from django.views.decorators.cache import cache_page
from django.core.cache import cache
from functools import wraps
# Встроенный декоратор для функций
def cache_result(timeout=3600):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# Генерируем ключ кеша на основе имени функции и параметров
cache_key = f"{func.__name__}:{args}:{kwargs}"
result = cache.get(cache_key)
if result is None:
result = func(*args, **kwargs)
cache.set(cache_key, result, timeout)
return result
return wrapper
return decorator
# Использование
@cache_result(timeout=1800)
def get_expensive_data(user_id):
# Дорогостоящая операция
return expensive_calculation(user_id)
Инвалидация кеша
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.cache import cache
from .models import Article
# Очищаем кеш при обновлении статьи
@receiver(post_save, sender=Article)
def invalidate_article_cache(sender, instance, **kwargs):
# Удаляем кеш списка статей
cache.delete('all_articles')
cache.delete('featured_articles')
# Удаляем кеш конкретной статьи
cache.delete(f'article:{instance.id}')
Кеширование с Vary HTTP headers
from django.views.decorators.cache import cache_page, vary_on_headers
from django.shortcuts import render
# Кешируем отдельно для каждого пользователя
@cache_page(60)
@vary_on_headers('Cookie')
def user_dashboard(request):
return render(request, 'dashboard.html', {'user': request.user})
# Кешируем отдельно для каждого User-Agent
@cache_page(60)
@vary_on_headers('User-Agent')
def home(request):
return render(request, 'home.html')
Низкоуровневое кеширование в шаблоне
{% load cache %}
<!-- Ключ кеша зависит от пользователя -->
{% cache 600 user_sidebar user.id %}
<aside class="sidebar">
<h3>Мой профиль</h3>
<p>{{ user.email }}</p>
<ul>
{% for notification in user.notifications %}
<li>{{ notification.message }}</li>
{% endfor %}
</ul>
</aside>
{% endcache %}
Best practices
1. Используй осмысленные ключи кеша:
# ПЛОХО
cache.set('key', data, 3600)
# ХОРОШО
cache.set(f'user_profile:{user_id}', user_data, 3600)
cache.set(f'category_products:{category_id}', products, 1800)
2. Выбирай правильный timeout:
# Для пользовательских данных — короче
cache.set('user_data', data, 300) # 5 минут
# Для статических данных — дольше
cache.set('categories', categories, 86400) # 1 день
# Для очень динамичных данных — вообще не кешируй
3. Инвалидируй кеш правильно:
from django.db.models.signals import post_delete
@receiver(post_delete, sender=Article)
def invalidate_on_delete(sender, instance, **kwargs):
cache.delete(f'article:{instance.id}')
cache.delete('all_articles')
4. Мониторь эффективность кеша:
from django.views.decorators.cache import cache_page
# Используй Django Debug Toolbar для анализа
# или добавь логирование попаданий/промахов
def log_cache_stats():
# Некоторые бэкенды поддерживают статистику
stats = cache._cache.get_stats() # Redis пример
print(f"Cache hits: {stats['hits']}, misses: {stats['misses']}")
Когда использовать кеширование
- Часто запрашиваемые данные — списки категорий, популярные посты
- Дорогостоящие операции — сложные аналитики, расчёты
- Медленные запросы к БД — запросы с multiple joins
- Внешние API запросы — данные от сторонних сервисов
Когда НЕ использовать:
- Критичные данные — актуальность важнее, чем скорость
- Личные данные — безопасность важнее
- Часто меняющиеся данные — инвалидация будет частой
Вывод: Кеширование — мощный инструмент для оптимизации Django приложений. Правильное использование может значительно улучшить производительность, но требует осмысленного подхода к инвалидации и выбору данных для кеша.