Django-fr | Documentation | Le framework de cache de Django

Django-fr

Documentation Django

Le framework de cache de Django

Un des aspects fondamental des sites web dynamiques est, évidemment, qu'ils sont dynamiques. A chaque fois qu'un utilisateur demande l'affichage d'une page, le serveur web effectue tout un ensemble de calculs -- allant des requêtes en base de données, jusqu'au rendu des gabarits, en passant par la logique métier -- afin de créer la page que vos visiteurs voient. Ceci est plus coûteux, en terme de surcharge de traitement, qu'une simple lecture de fichier sur le système de fichiers de votre serveur.

Pour la plupart des applications web, cette surcharge n'est pas un problème. La plupart des applications web ne sont pas le washingtonpost.com ou slashdot.org; ce sont simplement des sites de petites et moyennes taille avec un traffic de même ampleur. Mais pour les sites possédant un traffic moyen important, il est essentiel de réduire la surcharge autant que possible.

C'est à ce moment que le cache entre en jeu.

Mettre en cache un objet consiste à sauvegarder le résultat d'un calcul coûteux, de manière à ne pas effectuer le traitement la prochaine fois. Voici un pseudocode détaillant comme cela fonctionne pour les pages web gérées dynamiquement:

pour une URL donnée, essayer de trouver la page dans le cache
si la page est dans le cache:
    retourner la page cachée
sinon:
    générer la page
    sauvegarder la page générée dans le cache (pour la prochaine fois)
    retourner la page générée

Django fourni un système de cache robuste qui vous permet de sauvegarder des pages dynamiques afin de ne pas avoir à recalculer chaque requête. Par commodité, Django offre une granularité de cache sur plusieurs niveaux : vous pouvez mettre en cache le résultat de sortie de vues spécifiques, vous pouvez ne mettre en cache que les parties difficiles à restituer, ou encore, vous pouvez mettre en cache votre site dans son entier.

Django fonctionne aussi très bien avec les caches situés en amont, tels que Squid et le cache des navigateurs. C'est le genre de cache que vous ne contrôlez pas, mais sur lequel vous pouvez agir (via les entêtes HTTP) en indiquant quelles parties de votre site doivent être mises en cache, et comment.

Configuration du cache

Le système de cache ne nécessite qu'une petite partie de configuration. A savoir, vous n'avez besoin que de lui dire où les données seront stockées -- s'il s'agit de la base de données, du système de fichiers, ou directement en mémoire. C'est une décision importante car elle affecte les performances de votre cache; oui, certains types de cache sont plus rapide que d'autres.

Votre choix de cache est stocké dans le paramètre de configuration CACHE_BACKEND de votre fichier de configuration. Ce qui suit détaille les différents valeurs permises pour CACHE_BACKEND.

Memcached

De loin le plus rapide et le plus efficace des systèmes de cache disponibles pour Django, Memcached est un framework de cache entièrement basé sur la mémoire, initialement développé pour gérer les forts taux de charge du LiveJournal.com et par la suite versé dans le libre par Danga Interactive. Il est utilisé par des sites tels que Slashdot et Wikipedia pour réduire les accès en base de données et améliorer les performances de manière significative.

Memcached est disponible gratuitement sur http://danga.com/memcached/ . Il s'exécute en tant que démon et il lui est alloué une certaine quantité de RAM. Tout ce qu'il fait est de fournir une interface -- une interface super-rapide -- pour ajouter, récupérer et supprimer des données arbitraires en cache. Toutes les données étant directement stockées en mémoire, il n'y a donc pas de surcharge d'utilisation de la base de données ou du système de fichiers.

Après avoir installé Memcached, vous devrez installer la couche de liaison Python pour Memcached. Deux versions sont disponibles. Choisissez et installez un des modules suivants :

  • L'option la plus rapide est un module nommé cmemcache, disponible sur http://gijsbert.org/cmemcache/ . (Ce module est uniquement compatible avec la version de développement de Django. Django 0.96 est uniquement compatible avec la seconde option qui suit.)
  • Si vous ne pouvez pas installer cmemcache, vous pouvez installer python-memcached, disponible sur ftp://ftp.tummy.com/pub/python-memcached/ . Si cette URL est brisée allez simplement sur le site de Memcached (http://www.danga.com/memcached/) et récupérez la couche de liaison Python depuis la section "Client APIs".

Pour utiliser Memcached avec Django, affectez la valeur memcached://ip:port/ à CACHE_BACKEND, dans laquelle ip désigne l'adresse IP de votre démon Memcached et port est le port sur lequel Memcached s'exécute.

Dans cet exemple, Memcached s'exécute en local (127.0.0.1) sur le port 11211:

CACHE_BACKEND = 'memcached://127.0.0.1:11211/'

Une des fonctionnalités phares de Memcached est sa capacité partager le cache à travers plusieurs serveurs. Pour utiliser cette fonctionnalité ajoutez toutes les adresses de vos serveurs dans CACHE_BACKEND, séparées par un point virgule. Dans l'exemple qui suit, le cache est partagé à travers les instances Memcached s'exécutant aux adresses IP 172.19.26.240 et 172.19.26.242, toutes deux sur le port 11211:

CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'

Le cache basé sur la mémoire possède un inconvénient: du fait que les données sont gardées en mémoire, les données seront perdues si votre serveur tombe en panne. Clairement, la mémoire n'est pas destinée à la persistance de données. Ne dédiez donc pas uniquement votre gestion de cache sur la mémoire. En fait, aucun des systèmes de cache de Django ne doit être utilisé comme moyen de stockage permanent des données -- ils sont tous destinés à fournir des solutions de cache, et non de stockage -- mais nous appuyons sur ce point du fait que le cache basé sur la mémoire est particulièrement temporaire.

Cache via la base de données

Pour utiliser une table de données comme système de cache, premièrement, créez une table de cache dans votre base de données en exécutant la commande:

python manage.py createcachetable [nom_table_de_cache]

...dans laquelle [nom_table_de_cache] est le nom de la table à créer. (Ce nom peut être celui que vous voulez, tant qu'il s'agit d'un nom de table valide qui n'est pas déjà utilisé dans votre base de données.) Cette commande crée une unique table dans votre base de données dans le format propre utilisé par le système de cache de Django.

Une fois que vous avez créé cette table, affectez la valeur "db://nom_table" à CACHE_BACKEND, où nom_table correspond au nom de votre table. Dans cet exemple, le nom de la table de cache est ma_table_de_cache:

CACHE_BACKEND = 'db://ma_table_de_cache'

Le cache en base de données fonctionne de manière optimum lorsque vous possédez un serveur de base de données rapide et bien indéxée.

Cache via le système de fichiers

Pour sauvegarder les éléments du cache sur un système de fichiers, utilisez le type de cache "file://" pour CACHE_BACKEND. Par exemple, pour stocker les données en cache dans /var/tmp/cache_django, utilisez cette configuration:

CACHE_BACKEND = 'file:///var/tmp/cache_django'

Vous noterez qu'il y a trois barres obliques successives vers le début de cet exemple. Les deux premières concernent file://, et la troisième est la première lettre du chemin de répertoire, /var/tmp/cache_django.

Le chemin de répertoire doit être de type absolu -- c'est-à-dire qu'il doit commencer à partir de l'élément racine de votre système de fichiers. La barre oblique finale n'est pas obligatoire et ne revêt aucune importance particulière.

Assurez vous que le répertoire cible de la configuration existe bien et qu'il est accessible en lecture et écriture par l'utilisateur système exécutant votre serveur web. Pour poursuivre l'exemple précédent, si votre serveur est exécuté par l'utilisateur apache, assurez vous que le répertoire /var/tmp/cache_django existe et qu'il est accessible en lecture et écriture par l'utilisateur apache.

Cache via mémoire locale

Si vous voulez bénéficier des avantages de rapidité du cache en mémoire mais que vous ne pouvez pas exécuter Memcached, regardez du côté du système de cache de mémoire locale. Ce cache est multi-processus et thread-safe (exécution des processus parallèles sécurisée). Pour l'utiliser, affecter la valeur "locmem:///" à CACHE_BACKEND. Par exemple:

CACHE_BACKEND = 'locmem:///'

Cache basique (expérimental)

Un mono-processus basique de cache mémoire disponible via "simple:///". Il sauvegarde simplement les données en cache du processus en cours, impliquant qu'il ne peut être utilisé que dans des environnements de développement ou de test. Par exemple

CACHE_BACKEND = 'simple:///'

Nouveau dans la version de développement de Django: Ce système de cache est déprécié et sera supprimé dans une prochaine version. L'utilisation du système de cache locmem est maintenant recommandé.

Cache factice (expérimental)

Enfin, Django s'accompagne d'un cache factice qui n'effectue aucun travail de cache -- il implémente simplement l'interface de cache sans rien faire d'autre.

Ceci est utile si vous avez un site en production qui a de fort besoin en cache à plusieurs endroits différents mais un environnement de développement et/ou de test qui ne nécessite pas de cache. Ainsi, votre environnement de développement n'utilisera plus de cache, mais sans affecter celui de votre environnement de production. Pour activer le cache factice, assignez CACHE_BACKEND comme suit:

CACHE_BACKEND = 'dummy:///'

Arguments de CACHE_BACKEND

Tous les caches peuvent recevoir des arguments. Ils sont passés sous forme de query-string au paramètre de configuration CACHE_BACKEND. Les arguments possibles sont les suivants :

timeout
Temps d'expiration par défaut, en secondes, à utiliser par le cache. Défini par défaut à 5 minutes (300 secondes).
max_entries
Pour les caches bassique et via la base de données, le nombre maximum d'entrées permises en cache avant effacement. Par défaut à 300.
cull_percentage

Pourcentage d'entrées éliminées quand max_entries est atteint. Le véritable pourcentage est de 1/cull_percentage. De ce fait, l'affectation cull_percentage=3 entraînera la suppression d'1/3 des entrées lorsque max_entries est atteint.

Une valeur égale à 0 pour cull_percentage signifie la destruction totale du cache lorsque max_entries est atteint. Ceci rend l'élimination beaucoup plus rapide aux dépens de plus d'absence dans l'antémémoire.

Dans cet exemple, timeout à pour valeur 60:

CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60"

Dans cet exemple, timeout vaut 30 et max_entries est à 400:

CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=30&max_entries=400"

Les arguments non valides sont ignorés silencieusement, tout comme les valeurs qui leurs sont associées.

Le cache par site

Une fois le cache configuré la manière la plus simple de l'utiliser est encore de mettre en cache votre site dans son entier. Pour ce faire, ajoutez 'django.middleware.cache.CacheMiddleware' à votre paramètre de configuration MIDDLEWARE_CLASSES, comme dans l'exemple qui suit:

MIDDLEWARE_CLASSES = (
    'django.middleware.cache.CacheMiddleware',
    'django.middleware.common.CommonMiddleware',
)

(L'ordre des MIDDLEWARE_CLASSES importe. Voir Ordre des MIDDLEWARE_CLASSES ci-dessous)

Puis, ajoutez les paramètres de configuration obligatoires suivants dans votre fichier de configuration de Django:

  • CACHE_MIDDLEWARE_SECONDS -- Le nombre de secondes pendant lesquelles chaque page doit être cachée.
  • CACHE_MIDDLEWARE_KEY_PREFIX -- Si le cache est partagé à travers plusieurs sites utilisant la même installation de Django, affectez lui le nom du site, ou une autre chaîne de caractères unique pour cette instance de Django, afin de prévenir les interblocages de clés. Laissez vide si cela n'a pas d'importance pour vous.

Le middleware de cache met en cache toute page ne contenant pas de paramètre passé via GET ou POST. De manière optionnelle, si le paramètre CACHE_MIDDLEWARE_ANONYMOUS_ONLY contient la valeur True, seules les requêtes anonymes (i.e., celles qui ne sont pas exécutées par un utilisateur authentifié seront cachées. C'est une manière simple et efficace de désactiver le cache pour les pages spécifiques aux utilisateurs (incluant les pages de l'interface d'administration de Django). Notez que si vous utilisez CACHE_MIDDLEWARE_ANONYMOUS_ONLY, vous devriez vous assurez que vous avez bien activé AuthenticationMiddleware et que AuthenticationMiddleware soit placé avant CacheMiddleware dans vos MIDDLEWARE_CLASSES.

De plus, CacheMiddleware ajoute automatiquement quelques entrées dans chaque HttpResponse:

  • Assigne à l'entête Last-Modified la date et l'heure courante quand une nouvelle version (non caché) de la page est demandée.
  • Assigne à l'entête Expires la date et l'heure courante augmentée du nombre de secondes définies par CACHE_MIDDLEWARE_SECONDS.
  • Assigne à l'entête Cache-Control la durée de vie maximum de la page -- de même, basée sur le paramètre de configuration CACHE_MIDDLEWARE_SECONDS

Voir la documentation sur les middlewares pour en savoir plus sur les middleware.

Nouveau dans la version de développement de Django

Si une vue gère son propre temps d'expiration de cache (i.e. possède une section max-age dans son entête CacheControl) alors la page sera mise en cache jusqu'à expiration du temps, au lieu de CACHE_MIDDLEWARE_SECONDS. L'utilisation des décorateurs de django.views.decorators.cache facilite l'assignation du temps d'expiration pour une vue (via le décorateur cache_control) ou la désactivation du cache pour une vue (via le décorateur never_cache). Voir la section Utilisation d'autres entêtes pour plus de décorateurs.

Le cache par vue

Une manière plus granulaire d'utiliser le framework de cache est de mettre en cache le résultat de sortie de chaque vue. Le django.views.decorators.cache défini un décorateur cache_page qui mettra automatiquement en cache la réponse de la vue pour vous. C'est très facile à utiliser:

from django.views.decorators.cache import cache_page

def slashdot_cela(request):
    ...

slashdot_cela = cache_page(slashdot_cela, 60 * 15)

Ou, en utilisant la syntaxe des décorateurs de Python 2.4:

@cache_page(60 * 15)
def slashdot_cela(request):
    ...

cache_page ne prends qu'un seul argument : le temps d'expiration du cache, en secondes. Dans l'exemple ci-dessus, le résultat de la vue slashdot_cela() sera mis en cache pendant 15 minutes.

Cache des gabarits par fragments

Nouveau dans la version de développement de Django

Si vous avez besoin de plus de contrôle, vous pouvez aussi mettre en cache des fragments de gabarits en utilisant le tag de gabarit cache. Pour que votre gabarit puisse accéder à ce tag, ajoutez {% load cache %} vers le début de votre gabarit.

Le tag de gabarit {% cache %} met en cache le contenu du bloc pour la période de temps donnée. Il prend au moins deux arguments : le temps maximum de mise en cache, en secondes, et le nom du fragment de cache. Par exemple:

{% load cache %}
{% cache 500 barre_laterale %}
    .. barre_laterale ..
{% endcache %}

Certaines fois, vous aurez besoin de mettre en cache plusieurs copies d'un fragment dépendant de données dynamiques apparaissant au sein même du fragment. Par exemple, vous voudriez une copie séparée de la barre latérale utilisée dans l'exemple précédent pour chaque utilisateur de votre site. Pour ce faire, passez un argument supplémentaire au tag de gabarit {% cache %} pour identifier le fragment de manière unique:

{% load cache %}
{% cache 500 barre_laterale request.user.username %}
    .. barre_laterale pour l'utilisateur connecté ..
{% endcache %}

Il est tout a fait possible de spécifier plus d'un argument pour identifier le fragment. Passez autant d'arguments à {% cache %} que nécessaire.

L'API de cache de bas niveau

Des fois, cependant, mettre en cache l'intégralité d'une page ne vous intéresse pas forcément. Par exemple, vous pouviez trouver qu'il n'est nécessaire que de mettre en cache le résultat d'une requête en base de données coûteuse. Dans ce genre de cas, vous pouvez utiliser l'API de cache de bas niveau pour mettre en cache des objets avec le niveau de granularité de votre choix.

L'API de cache est simple. Le module de cache, django.core.cache, met à disposition un objet cache automatiquement créé selon le paramètre de configuration CACHE_BACKEND:

>>> from django.core.cache import cache

L'interface de base est set(clé, valeur, temps_expiration_en_secondes) et get(clé):

>>> cache.set('ma_clé, 'bonjour, monde!', 30)
>>> cache.get('my_clé)
'bonjour, monde!'

L'argument temps_expiration_en_secondes est optionnel et est par défaut égal à la valeur définie dans le paramètre de configuration CACHE_BACKEND (expliqué plus haut).

Si l'objet n'existe pas en cache, cache.get() retourne None:

>>> cache.get('une_autre_clé')
None

# Attendre 30 secondes que 'ma_clé' expire...

>>> cache.get('ma_clé)
None

get() peut prendre un argument default:

>>> cache.get('ma_clé', 'est expiré')
'est expiré'

Nouveau dans la version de développement de Django Pour ajouter une clé uniquement si elle n'existe pas déjà, utilisez la méthode add(). Elle prend les mêmes paramètres que set(), sauf qu'elle n'essayera pas de mettre à jour le cache si la clé spécifiée est déjà présente:

>>> cache.set('ajout_clé', 'Valeur initiale')
>>> cache.add('ajout_clé', 'Nouvelle valeur')
>>> cache.get('ajout_clé')
'Valeur initiale'

Il y aussi une méthode get_many() qui n'attaque le cache qu'une seule fois. get_many() retourne un dictionnaire avec toutes les clés que vous avez demandé pour celles qui existent encore en cache (et n'ont pas expiré):

>>> cache.set('a', 1)
>>> cache.set('b', 2)
>>> cache.set('c', 3)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}

Finalement, vous pouvez directement supprimer des clés avec delete(). C'est une manière facile de supprimer un objet particulier du cache:

>>> cache.delete('a')

C'est tout. Le cache possède quelques restrictions : Vous pouvez mettre en cache tout objet qui se conserve de manière sécurisée tandis que les clés doivent être des chaînes de caractères.

Les caches en amont

Jusqu'ici, ce document s'en est tenu à la mise en cache de vos données. Mais un autre type de cache est aussi pertinent pour le développement web: le cache géré par les serveurs de cache en "amont". Ce sont des systèmes qui mettent en cache les pages pour les utilisateurs avant même que la requête n'atteigne votre site web.

Voici quelques exemples de caches en amont:

  • Votre FAI peut mettre en cache certaines pages. Ainsi, si vous requêtez le page de undomaine.com, votre FAI vous enverra la page sans accéder directement à undomaine.com.
  • Votre site Django est derrière un proxy web Squid qui met en cache les pages pour améliorer les performances. Dans ce genre de cas, chaque requête est d'abord gérée ar Squid, et ne la repassera à votre application que si besoin est.
  • Votre navigateur web met aussi en cache les pages. Si une page web envoi les bons entêtes, votre navigateur utilisera la copie locale (en cache) pour les requêtes suivantes, sur cette page.

Le cache exercé en amont amène un bon boost de performance, mais il y a un danger à son utilisation: Le contenu des pages web diffèrent en regard de l'authentification, de l'hôte ou d'autres variables, et les systèmes de cache qui sauvegarde les pages en aveugle en se basant seulement sur l'URL peuvent exposer des données incorrectes ou sensibles aux utilisateurs qui suivent et demandent ces même pages.

Par exemple, disons que vous faîtes fonctionner une application web de gestion de courriels, et que le contenu de la page "boîte de réception" dépend de l'utilisateur qui est connecté. Si un FAI met aveuglément en cache votre site, alors le premier utilisateur qui se connectera via cet FAI verra apparaître sa page contenant ses données personnelles sur celle des utilisateurs qui suivent. Ce qui n'est pas top.

Heureusement, HTTP apporte une solution à ce problème: Un ensemble d'entêtes HTTP existe pour instruire les mécanismes de cache et différencier le contenu de cache en fonction de variables données, et d'ordonner aux mécanismes de cache de ne pas mettre en cache certaines pages.

Utilisation des entêtes Vary

Un de ces entêtes est Vary. Il défini quelles sont les entêtes de la requête que le mécanisme de cache doit prendre en compte lors de la construction de sa clé de cache. Par exemple, si le contenu d'une page web dépend de la langue préférée de l'utilisateur, la page est dite à "varier en fonction de la langue".

Par défaut, le système de cache de Django crée sa clé de cache en utilisant le chemin requêté -- e.g., "/nouvelles/2005/juin/23/vol_de_banque/". Ceci veut dire que chaque requête sur cette URL utilisera la même version en cache, sans se soucier des différences émanant des agents utilisateurs tels que les cookies ou la langue.

C'est à ce moment que Vary entre en jeu.

Si votre page Django génère un contenu différent en fonction des entêtes des requêtes -- tels les cookies, la langue ou l'agent utilisateur -- vous aurez besoin de l'entête Vary pour spécifier au mécanisme de cache que le contenu de votre page dépend de ce genre de chose.

Pour faire cela avec Django, utilisez le décorateur de vue taillé sur mesure vary_on_headers, de cette manière:

from django.views.decorators.vary import vary_on_headers

# Syntaxe Python 2.3.
def ma_vue(request):
    ...
ma_vue = vary_on_headers(ma_vue, 'User-Agent')

# Syntaxe décorateur de Python 2.4.
@vary_on_headers('User-Agent')
def ma_vue(request):
    ...

Ici, un mécanisme de cache (tel que le middleware de cache propre à Django) mettra en cache une version séparée de la page pour chaque agent utilisateur unique.

L'avantage d'utiliser le décorateur vary_on_headers au lieu d'effectuer manuellement le paramétrage de l'entête Vary (en utilisant quelque chose comme response['Vary'] = 'user-agent') est que le décorateur ajoute la donnée d'entête Vary (qui existe peut être déjà) au lieu de simplement la redéfinir.

Vous pouvez ajouter plusieurs entêtes à vary_on_headers():

@vary_on_headers('User-Agent', 'Cookie')
def ma_vue(request):
    ...

Du fait que la dépendance via un cookie est un cas commun, il existe un décorateur vary_on_cookie. Ces deux vues sont équivalentes:

@vary_on_cookie
def ma_vue(request):
    ...

@vary_on_headers('Cookie')
def ma_vue(request):
    ...

Vous noterez aussi que les entêtes que vous passez à vary_on_headers ne sont pas sensibles à la casse. "User-Agent" est identique à "user-agent".

Vous pouvez aussi directement utiliser l'assistant django.utils.cache.patch_vary_headers:

from django.utils.cache import patch_vary_headers
def ma_vue(request):
    ...
    reponse = render_to_response('nom_gabarit', context)
    patch_vary_headers(reponse, ['Cookie'])
    return reponse

patch_vary_headers prends une instance HttpResponse en tant que premier argument et une liste ou un tuple de noms d'entêtes en second argument.

Pour en savoir plus sur les headers Vary, regardez la spécification officielle de vary.

Contrôle du cache: Utilisation d'autres entêtes

Un autre problème avec le cache est la protection de vos données et la question de savoir où vos données doivent être stockées parmi la cascade de systèmes de cache.

Un utilisateur est généralement en proie à deux types de cache: son propre cache de navigateur (un cache privé) et le cache de son fournisseur d'accès (un cache public). Un cache public est utilisé par de multiple utilisateurs et contrôlé par d'autres. Ceci pose problème pour les données sensibles: Vous ne voulez pas, par exemple, que votre compte bancaire soit stocké dans un cache public.

La solution est d'indiquer que la page en cache doit être "privée". Pour faire cela dans Django, utilisez le décorateur de vue cache_control. Exemple:

from django.views.decorators.cache import cache_control
@cache_control(private=True)
def ma_vue(request):
    ...

Ce décorateur prendra soin d'envoyer l'entête HTTP appropriée de manière transparente.

Il y a d'autres manières de contrôler les paramètres de cache. Par exemple, HTTP permet aux applications de faire ce qui suit:

  • Définir le temps maximum pendant lequel une page est en cache.
  • Déterminer si le cache doit systématiquement vérifier qu'une nouvelle version existe, ne délivrant le contenu en cache seulement s'il n'y a pas eu de changements. (Certains systèmes de cache peuvent délivrer du contenu en cache même si la page côté serveur a changé -- tout simplement parce qu'une copie existe en cache et qu'elle n'est pas expirée.)

Dans Django, utilisez le décorateur de vue cache_control pour spécifier ce genre de paramètres de cache. Dans l'exemple qui suit, cache_control indique aux systèmes de caches de revalider leur cache à chaque accés et de ne garder en cache les éléments que pendant, au plus, 3600 secondes:

from django.views.decorators.cache import cache_control
@cache_control(must_revalidate=True, max_age=3600)
def ma_vue(request):
    ...

Toutes les directives Cache-Control valides pour HTTP le sont aussi pour cache_control(). Voici la liste complète:

  • public=True
  • private=True
  • no_cache=True
  • no_transform=True
  • must_revalidate=True
  • proxy_revalidate=True
  • max_age=nombre_secondes
  • s_maxage=nombre_secondes

Pour des plus amples détails sur les directives Cache-Control de HTTP, regardez la spécification de Cache-Control.

(Notez que le middleware de cache assigne déjà le max-age de l'entête via la valeur du paramètre de configuration CACHE_MIDDLEWARE_SETTINGS. Si vous utilisez une autre valeur de max_age dans le décorateur cache_control, ce dernier obtiendra la précédente, et la valeur de l'entité sera correctement assignée.)

Si vous désirez utiliser les entêtes pour désactiver le cache dans son entier, le décorateur de vue django.views.decorators.cache.never_cache ajoute des entêtes pour s'assurer que la réponse ne sera pas mise en cache par les navigateurs ou d'autres systèmes de caches. Exemple:

from django.views.decorators.cache import never_cache
@never_cache
def ma_vue(request):
    ...

Autres optimisations

Django est fourni avec plusieurs autres middlewares qui peuvent vous aider à optimiser les performances de vos applications:

  • django.middleware.http.ConditionalGetMiddleware ajoute le support des GET conditionnels. Ceci utilise les entêtes ETag et Last-Modified.
  • django.middleware.gzip.GZipMiddleware compresse le contenu pour les navigateurs acceptant la compression gzip (tous les navigateurs modernes).

Ordre des MIDDLEWARE_CLASSES

Si vous utilisez CacheMiddleware, il est important de le disposer à la bonne place dans le paramètre de configuration MIDDLEWARE_CLASSES, du fait que le middleware de cache à besoin de connaître sur quels entêtes le contenu du cache varie. Le middleware ajoute systématiquement quelque chose à l'entête Vary de la réponse dès qu'il le peut.

Ajoutez le CacheMiddleware avant tout middleware pouvant ajouter quelque chose à l'entête Vary (les middlewares réponse sont appliqués en sens inverse). Les middlewares suivants sont concernés:

  • SessionMiddleware ajoute Cookie
  • GZipMiddleware ajoute Accept-Encoding
  • LocaleMiddleware ajoute Accept-Language