web-dev-qa-db-fra.com

cache_page avec des vues basées sur les classes

J'essaie de faire cache_page avec des vues basées sur la classe (TemplateView) et je ne suis pas en mesure de le faire. J'ai suivi les instructions ici:

Django - Echec de la mise en cache des URL pour les vues basées sur des classes

ainsi qu'ici:

https://github.com/msgre/hazard/blob/master/hazard/urls.py

Mais je reçois cette erreur:

cache_page has a single mandatory positional argument: timeout

J'ai lu le code pour cache_page et il a ceci:

if len(args) != 1 or callable(args[0]):
    raise TypeError("cache_page has a single mandatory positional argument: timeout")
cache_timeout = args[0]

ce qui signifie qu'il ne permettra pas plus d'un argument. Existe-t-il un autre moyen de faire fonctionner cache_page? J'ai creusé dans cela pendant un certain temps ...

Il semble que les solutions précédentes ne fonctionneront plus

22
KVISH

Selon le cache des documents docs, la méthode correcte pour mettre en cache un CBV est

url(r'^my_url/?$', cache_page(60*60)(MyView.as_view())),

Notez que la réponse que vous avez liée est obsolète. L'ancienne façon d'utiliser le décorateur a été supprimée ( changeset ).

44
Alasdair

encore un autre bon exemple CacheMixin de cyberdelia github

class CacheMixin(object):
    cache_timeout = 60

    def get_cache_timeout(self):
        return self.cache_timeout

    def dispatch(self, *args, **kwargs):
        return cache_page(self.get_cache_timeout())(super(CacheMixin, self).dispatch)(*args, **kwargs)

cas d'utilisation: 

from Django.views.generic.detail import DetailView


class ArticleView(CacheMixin, DetailView):
    cache_timeout = 90
    template_name = "article_detail.html"
    queryset = Article.objects.articles()
    context_object_name = "article"
14
madjardi

Vous pouvez simplement décorer la classe elle-même au lieu de remplacer la méthode de répartition ou d'utiliser un mixin.

Par exemple

from Django.views.decorators.cache import cache_page
from Django.utils.decorators import method_decorator

@method_decorator(cache_page(60 * 5), name='dispatch')
class ListView(ListView):
...

Django docs sur décorer une méthode dans une vue basée sur les classes.

6
Dayson

Vous pouvez l'ajouter en tant que décorateur de classe et même en ajouter plusieurs à l'aide d'une liste:

@method_decorator([vary_on_cookie, cache_page(900)], name='dispatch')
class SomeClass(View):
   ...
3

J'ai créé ce petit générateur de mixin pour faire la mise en cache dans le fichier views, au lieu de dans l'URL conf:

def CachedView(cache_time=60 * 60):
    """
    Mixing generator for caching class-based views.

    Example usage:

    class MyView(CachedView(60), TemplateView):
        ....

    :param cache_time: time to cache the page, in seconds
    :return: a mixin for caching a view for a particular number of seconds
    """
    class CacheMixin(object):
        @classmethod
        def as_view(cls, **initkwargs):
            return cache_page(cache_time)(
                super(CacheMixin, cls).as_view(**initkwargs)
            )
    return CacheMixin
3
Krystian Cybulski

Encore une autre réponse, nous avons trouvé que ceci était plus simple et spécifique aux vues modèles. 

class CachedTemplateView(TemplateView):
    @classonlymethod
    def as_view(cls, **initkwargs): #@NoSelf
        return cache_page(15 * 60)(super(CachedTemplateView, cls).as_view(**initkwargs))
2
Kevin Parker

Je n'ai pas trouvé de solution de cache efficace pour les vues basées sur les classes et j'ai créé le mien: https://Gist.github.com/svetlyak40wt/1112126018

C'est un mix pour une classe. Ajoutez-le avant la classe de base principale et implémentez la méthode get_cache_params comme ceci:

def get_cache_params(self, *args, **kwargs):
   return ('some-prefix-{username}'.format(
       username=self.request.user.username),
            3600)
2

Voici ma variante du CachedView() mixin. Je ne souhaite pas mettre la vue en cache si l'utilisateur est authentifié, car son affichage des pages lui sera propre (par exemple, son nom d'utilisateur, son lien de déconnexion, etc.).

class CacheMixin(object):
    """
    Add this mixin to a view to cache it.

    Disables caching for logged-in users.
    """
    cache_timeout = 60 * 5 # seconds

    def get_cache_timeout(self):
        return self.cache_timeout

    def dispatch(self, *args, **kwargs):
        if hasattr(self.request, 'user') and self.request.user.is_authenticated:
            # Logged-in, return the page without caching.
            return super().dispatch(*args, **kwargs)
        else:
            # Unauthenticated user; use caching.
            return cache_page(self.get_cache_timeout())(super().dispatch)(*args, **kwargs)
0
Phil Gyford