Кэширование Django только для аутентифицированных пользователей

Вопрос

В Django, как создать единую кешированную версию страницы (то же самое для всех пользователей), которая доступна только для аутентифицированных пользователей?

Настроить

Страницы, которые я хочу кэшировать, доступны только для аутентифицированных пользователей (они используют @login_required в представлении). Эти страницы одинаковы для всех пользователей, vary_on_headers проверку подлинности (например, нет необходимости vary_on_headers на основе уникальных пользователей).

Однако я не хочу, чтобы эти кэшированные страницы были видны пользователям, не прошедшим проверку подлинности.

То, что я пробовал до сих пор

  • Кэш уровня страницы (отображает страницы, предназначенные для входа в систему пользователям без регистрации)
  • Посмотрел на использование vary_on_headers , но мне не нужны индивидуально кэшированные страницы для каждого пользователя
  • Я проверил кэширование фрагмента шаблона, но, если я не смущен, это не удовлетворит мои потребности
  • Существенный поиск (кажется, что все хотят сделать обратное)

Благодаря!

Пример просмотра

 @login_required @cache_page(60 * 60) def index(request): '''Display the home page''' return render(request, 'index.html') 

settings.py (соответствующая часть)

 # Add the below for memcache MIDDLEWARE_CLASSES += ( 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', ) # Enable memcache # https://devcenter.heroku.com/articles/memcache#using_memcache_from_python CACHES = { 'default': { 'BACKEND': 'django_pylibmc.memcached.PyLibMCCache' } } 

Решение

Основываясь на ответе @Tisho, я решил эту проблему

  1. Создание файла decorators.py в моем приложении
  2. Добавление к нему приведенного ниже кода
  3. Импорт функции в views.py
  4. Применение его в качестве декоратора к представлениям, которые я хотел кэшировать только для зарегистрированных пользователей

decorators.py

 from functools import wraps from django.views.decorators.cache import cache_page from django.utils.decorators import available_attrs def cache_on_auth(timeout): def decorator(view_func): @wraps(view_func, assigned=available_attrs(view_func)) def _wrapped_view(request, *args, **kwargs): if request.user.is_authenticated(): return cache_page(timeout)(view_func)(request, *args, **kwargs) else: return view_func(request, *args, **kwargs) return _wrapped_view return decorator 

Для зарегистрированных пользователей он будет кэшировать страницу (или обслуживать их в кешированной странице) для не зарегистрированных пользователей, она просто даст им обычный вид, который был украшен с помощью @login_required и потребовал бы, чтобы они @login_required в систему.

3 Solutions collect form web for “Кэширование Django только для аутентифицированных пользователей”

По умолчанию разработчик cache_page принимает переменную key_prefix . Однако он может быть передан только как строковый параметр. Таким образом, вы можете написать свой собственный декоратор, который будет динамически изменять этот prefix_key на is_authenticated значения is_authenticated . Вот пример:

 from django.views.decorators.cache import cache_page def cache_on_auth(timeout): def decorator(view_func): @wraps(view_func, assigned=available_attrs(view_func)) def _wrapped_view(request, *args, **kwargs): return cache_page(timeout, key_prefix="_auth_%s_" % request.user.is_authenticated())(view_func)(request, *args, **kwargs) return _wrapped_view return decorator 

а затем использовать его в представлении:

 @cache_on_auth(60*60) def myview(request) 

Затем сгенерированная cache_key будет выглядеть так:

 cache key: views.decorators.cache.cache_page._auth_False_.GET.123456.123456 

если пользователь аутентифицирован и

 cache key: views.decorators.cache.cache_page._auth_True_.GET.789012.789012 

если пользователь не прошел аутентификацию.

Если украшатель @wrap в ответе @Tisho заставляет ваш мозг болеть, или если явное решение лучше, чем неявное, вот простой процедурный способ обслуживания разных результатов кеша:

 from django.views.decorators.cache import cache_page def index(request): """ :type request: HttpRequest """ is_authenticated = request.user.is_authenticated() if is_authenticated: return render_user(request) else: return render_visitor(request) @cache_page(5, key_prefix='user_cache') def render_user(request): print 'refreshing user_cache' return render(request, 'home-user.html', {}) @cache_page(10, key_prefix='visitor_cache') def render_visitor(request): print 'refreshing visitor_cache' return render(request, 'home-visitor.html', {}) 

Я бы посоветовал использовать промежуточное ПО кэша, если вы хотите тонкую настройку своих способностей кэширования.

Однако, если вы хотите сохранить его, вы можете попробовать что-то вроде (не говоря, что он будет работать как есть, но что-то похожее на него):

 @never_cache def dynamic_index(request): # do dynamic stuff def cached_index(request): return dynamic_index(request) @never_cache def index(request): if request.user.is_authenticaded(): return cached_index(request) return dynamic_index(request) 

В худшем случае вы можете использовать cache.set ('view_name', template_rendering_result) и cache.get, чтобы просто кэшировать HTML вручную.

  • как вернуть все memcached значения в Google App Engine?
  • Проблемы с производительностью memcache App Engine / ndb.get_multi
  • Как предотвратить сброс memcache AppEngine
  • Как экспортировать все ключи и значения из memcached с помощью python-memcache?
  • Удаление определенных элементов из кеша Django?
  • Как кэшировать вызовы API Django Rest Framework?
  • Пилоны и Memcached
  • Обмен Memcache с PHP и Python
  • Python - лучший язык программирования в мире.