1

I have a view which I want to cache only for unauthenticated users. The view should be something like this:

@cache_page_for_guests(60 * 15)
def my_view(request):

I've looked at the docs but could not but could not find any hints about this.

Actually my question is exactly as this, which is unanswered, and I could not make sense of the comments.

So appreciate your help.

Milkyway
  • 705
  • 3
  • 12
  • 25

2 Answers2

1

Write a custom decorator like this:

from django.views.decorators.cache import cache_page

def cache_page_for_guests(cache_life_span):
    def decorator(view_func):
        @wraps(view_func, assigned=available_attrs(view_func))
        def _wrapped_view(request, *args, **kwargs):
            return cache_page(cache_life_span, key_prefix="_auth_%s_" % not request.user.is_authenticated())(view_func)(request, *args, **kwargs)
        return _wrapped_view
    return decorator

Then in view

@cache_page_for_guests(60 * 15)
def my_view(request):
shafik
  • 6,098
  • 5
  • 32
  • 50
  • I get syntax error in `return cache_page(cache_life_span, key_prefix="_auth_%s_" % not request.user.is_authenticated())(view_func)(request, *args, **kwargs)` – Milkyway Apr 04 '19 at 16:54
  • Try this `return cache_page(cache_life_span, key_prefix="_auth_%s_" % request.user.is_authenticated() is False)( view_func)(request, *args, **kwargs)` – shafik Apr 04 '19 at 17:03
  • Now I get `NameError: global name 'wraps' is not defined` error. – Milkyway Apr 04 '19 at 17:06
  • Import it like this `from django.utils.six import wraps` – shafik Apr 04 '19 at 17:07
  • Now I get `NameError: global name 'available_attrs' is not defined` – Milkyway Apr 04 '19 at 17:13
  • 1
    from django.utils.decorators import available_attrs – shafik Apr 04 '19 at 17:14
  • The error is gone, but the decorator does not work correctly: It caches the page for authenticated user too. So I had to un-accept your answer. – Milkyway Apr 04 '19 at 17:29
1
from functools import wraps
from django.views.decorators.cache import cache_page


def cache_page_for_guests(*cache_args, **cache_kwargs):
    def inner_decorator(func):
        @wraps(func)
        def inner_function(request, *args, **kwargs):
            if not request.user.is_authenticated:
                return cache_page(*cache_args, **cache_kwargs)(func)(request, *args, **kwargs)
           return func(request, *args, **kwargs)
        return inner_function
    return inner_decorator

you can use cache_page_for_guest just like cache_page. It'll accept the same arguments as of cache_page. Based on the user's authentication, it'll show either a normal view or a cached view.

@cache_page_for_guests(60 * 15)
def my_view(request):