22

質問

Djangoで、認証されたユーザーにのみ表示される単一のキャッシュバージョンのページ(すべてのユーザーに同じ)を作成するにはどうすればよいですか?

設定

キャッシュしたいページは、認証されたユーザーのみが利用できます(ビューで使用@login_requiredします)。これらのページは、認証されたすべてのユーザーで同じです(たとえば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おり、ログインが必要になります。

4

4 に答える 4

29

デフォルトのcache_pageデコレータは、と呼ばれる変数を受け入れますkey_prefix。ただし、文字列パラメータとしてのみ渡すことができます。prefix_keyしたがって、値に基づいてこれを動的に変更する独自のデコレータを作成できます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

ユーザーが認証されていない場合。

于 2012-07-28T19:22:25.640 に答える
2

@Tisho回答の@wrapデコレータが脳を傷つける場合、または明示的な解決策が暗黙的な解決策よりも優れている場合、さまざまなキャッシュ結果を提供する簡単な手順の方法は次のとおりです。

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', {})
于 2014-01-10T02:35:50.930 に答える
0

キャッシュ機能を微調整したい場合は、キャッシュミドルウェアを使用しないことをお勧めします。

ただし、それを維持したい場合は、次のようなことを試すことができます(そのままで機能するとは言えませんが、似たようなものです)。

@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を手動でキャッシュすることができます。

于 2012-07-28T19:31:18.173 に答える
-1

これは非常に古い質問ですが、これを解決するための新しい選択肢があります。

データを保護するために、デコレータcache_controlの受け渡しをprivate使用できます。True

于 2020-05-20T14:07:53.500 に答える