Pourquoi Caching avec Django et Redis ?
Dans un monde où la performance est cruciale, le caching joue un rôle essentiel pour améliorer les temps de réponse des applications web. En utilisant Django en tant que framework Python, nous avons l'avantage de bénéficier d'un système de cache intégré. Cependant, pour une grande échelle et des performances optimisées, il est recommandé d'utiliser un service de cache dédié comme Redis.
Un cas concret de l'utilisation du caching serait dans le cas d'une application e-commerce où les produits sont fréquemment consultés. En utilisant Django avec Redis, nous pouvons stocker en mémoire les informations des produits et les rafraîchir régulièrement pour s'assurer que la donnée est toujours à jour.
Prerequis
- Connaissance approfondie de Django
- Python 3.x installé
- Redis installé (version recommandée : >= 4.0)
- Un environnement virtuel configuré
Installation des outils
Créez un environnement virtuel :
python -m venv venv source venv/bin/activate # Sous Linux/MacOS .\venv\Scripts\activate # Sous WindowsInstallez Django et Redis-Py :
pip install django redisInstallez Redis sur votre système :
- Sur Ubuntu/Debian :
sudo apt update sudo apt install redis-server - Sur MacOS (avec Homebrew) :
brew install redis
- Sur Ubuntu/Debian :
Concepts fondamentaux
1. Cache en Django
Django offre un système de cache intégré qui peut être utilisé pour stocker des données temporaires en mémoire. Voici comment il fonctionne :
from django.core.cache import cache
## Stocker une donnée dans le cache
cache.set('my_key', 'my_value', timeout=30) # Timeout en secondes
## Récupérer une donnée du cache
value = cache.get('my_key')
## Supprimer une donnée du cache
cache.delete('my_key')
2. Redis comme backend de cache
Redis est un système de cache dédié qui offre des performances et des fonctionnalités avancées en matière de stockage en mémoire. Pour utiliser Redis avec Django, nous devons configurer le backend de cache.
## settings.py
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
3. Utilisation de decorators pour le caching
Django fournit des decorators pour appliquer le caching à des vues spécifiques.
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # Cache pendant 15 minutes
def my_view(request):
return render(request, 'my_template.html')
Mise en pratique : projet fil rouge
Pour illustrer l'utilisation du caching avec Django et Redis, nous allons créer un simple gestionnaire de tâches. Ce projet comprendra les fonctionnalités suivantes :
- Ajouter une nouvelle tâche
- Afficher la liste des tâches
- Marquer une tâche comme terminée
Étape 1 : Configuration du project Django
Créez un nouveau projet Django :
django-admin startproject task_manager
cd task_manager
Ajoutez Redis au backend de cache dans settings.py :
## settings.py
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
Étape 2 : Création d'un modèle
Créez un nouveau modèle pour les tâches dans models.py :
## models.py
from django.db import models
class Task(models.Model):
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
def __str__(self):
return self.title
Migrate le modèle :
python manage.py makemigrations
python manage.py migrate
Étape 3 : Création d'un serializer
Créez un serializer pour les tâches dans serializers.py :
## serializers.py
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = '__all__'
Étape 4 : Création d'un serializer pour les vues API
Créez un serializer pour les vues API dans views.py :
## views.py
from rest_framework import generics
from .models import Task
from .serializers import TaskSerializer
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # Cache pendant 15 minutes
class TaskList(generics.ListAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer
@cache_page(60 * 15)
class TaskDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer
Étape 5 : Configuration des routes API
Ajoutez les routes API dans urls.py :
## urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import TaskList, TaskDetail
router = DefaultRouter()
router.register(r'tasks', TaskList)
urlpatterns = [
path('', include(router.urls)),
]
Étape 6 : Création d'une interface utilisateur simple
Créez une interface utilisateur simple pour ajouter et afficher les tâches dans views.py :
## views.py
from django.shortcuts import render, redirect
from .models import Task
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def task_list(request):
tasks = Task.objects.all()
if request.method == 'POST':
title = request.POST.get('title')
Task.objects.create(title=title)
return redirect('task_list')
return render(request, 'task_list.html', {'tasks': tasks})
Créez la template task_list.html dans le dossier templates :
<!-- templates/task_list.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Task Manager</title>
</head>
<body>
<h1>Task List</h1>
<form method="post">
{% csrf_token %}
<input type="text" name="title" placeholder="Add new task">
<button type="submit">Submit</button>
</form>
<ul>
{% for task in tasks %}
<li>task.title - task.completed</li>
{% endfor %}
</ul>
</body>
</html>
Ajoutez la route pour l'interface utilisateur dans urls.py :
## urls.py
from django.urls import path
from .views import task_list
urlpatterns = [
path('', task_list, name='task_list'),
]
Étape 7 : Configuration du projet Django
Enfin, configurez votre projet Django pour inclure les applications nécessaires. Dans settings.py, ajoutez :
## settings.py
INSTALLED_APPS = [
...
'rest_framework',
]
Erreurs frequentes et debugging
1. Erreur : Cache non mis à jour
Code incorrect :
## views.py
from django.views.decorators.cache import cache_page
from .models import Task
@cache_page(60 * 15)
def task_list(request):
tasks = Task.objects.all()
return render(request, 'task_list.html', {'tasks': tasks})
Code correct :
## views.py
from django.views.decorators.cache import cache_page
from .models import Task
@cache_page(60 * 15)
def task_list(request):
tasks = list(Task.objects.all())
return render(request, 'task_list.html', {'tasks': tasks})
2. Erreur : Cache expiré trop rapidement
Code incorrect :
## settings.py
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
Code correct :
## settings.py
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'TIMEOUT': 3600, # Cache pendant 1 heure
}
}
}
3. Erreur : Cache non mis en place
Code incorrect :
## views.py
from django.views.decorators.cache import cache_page
from .models import Task
@cache_page(60 * 15)
def task_list(request):
tasks = Task.objects.all()
return render(request, 'task_list.html', {'tasks': tasks})
Code correct :
## views.py
from django.views.decorators.cache import cache_page
from .models import Task
@cache_page(60 * 15)
def task_list(request):
tasks = list(Task.objects.all())
return render(request, 'task_list.html', {'tasks': tasks})
Pour aller plus loin
1. Utilisation des pipelines Redis
Les pipelines Redis permettent d'envoyer plusieurs commandes en même temps pour optimiser les performances.
## views.py
import redis
from django.conf import settings
redis_client = redis.StrictRedis.from_url(settings.CACHES['default']['LOCATION'])
pipeline = redis_client.pipeline()
pipeline.set('my_key', 'my_value')
pipeline.expire('my_key', 30)
pipeline.execute()
2. Utilisation de Redis pour stocker des objets complexes
Redis peut être utilisé pour stocker des objets complexes en sérialisant et désérialisant les données.
## views.py
import json
from django.conf import settings
from django.core.cache import cache
redis_client = redis.StrictRedis.from_url(settings.CACHES['default']['LOCATION'])
data = {'key': 'value'}
redis_client.set('my_key', json.dumps(data), ex=30)
3. Utilisation de Redis pour les événements en temps réel
Redis est souvent utilisé pour gérer des événements en temps réel dans les applications web.
## views.py
import redis
from django.conf import settings
redis_client = redis.StrictRedis.from_url(settings.CACHES['default']['LOCATION'])
def handle_event(request):
event_data = request.POST.get('data')
redis_client.publish('my_channel', event_data)
Défi pratique
Créez une application web simple qui utilise Django et Redis pour stocker des données utilisateur en temps réel. L'application devrait permettre aux utilisateurs de s'inscrire, de se connecter et de partager leurs informations en temps réel.