2

私は Django 1.4 プロジェクトに取り組んでおり、ここで説明されているように、サイトごとのキャッシュを使用して 1 つの単純なアプリケーションを作成しています。

https://docs.djangoproject.com/en/dev/topics/cache/#the-per-site-cache

ローカルの Memcached サーバーを正しくセットアップし、ページがキャッシュされていることを確認しました。

次に、認証されたユーザーのページをキャッシュしたくないので、CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True を設定します。

テンプレートからユーザー情報にアクセスできるように render_to_response と RequestContext を含むテンプレートを返す単純なビューでテストしていますが、キャッシュはこれまでのところうまく機能しています。つまり、匿名ユーザーのためだけにページをキャッシュします。

そして、ここに私の問題があります。ユーザー情報にアクセスしない別のテンプレートを使用して別のビューを作成したところ、ユーザーが認証されていてもページがキャッシュされていることに気付きました。多くのことをテストした後、テンプレートがユーザー コンテキスト変数から何かを出力しなかった場合、認証されたユーザーはキャッシュされたページを取得していたことがわかりました。テストは非常に簡単です。テンプレートにユーザーを出力すると、認証されたユーザーのページはキャッシュされません。テンプレートでユーザーを削除し、認証中にページを更新し、HTTP ヘッダーを確認すると、取得していることに気付くでしょう。キャッシュされたページ。問題をより明確に確認するには、変更の間にキャッシュをクリアする必要があります。

もう少しテストしたところ、テンプレートでユーザーを削除し、request.user をビュー (開発サーバー コンソールに出力) に出力できることがわかりました。また、キャッシュされたページを認証済みページに表示する問題も修正されました。ユーザーですが、それは醜いハックです。

同様の問題がここで報告されましたが、回答が得られませんでした:

https://groups.google.com/d/topic/django-users/FyWmz9csy5g/discussion

おそらく、user.is_authenticated() をチェックする条件付きデコレーターを作成し、それに基づいてビューで @never_cache を使用することはできますが、それはサイトごとのキャッシュを使用する目的を無効にしているようですよね?

"""
A decorator to bypass per-site cache if the user is authenticated. Based on django.views.decorators.cache.never_cache.
See: http://stackoverflow.com/questions/12060036/why-django-1-4-per-site-cache-does-not-work-correctly-with-cache-middleware-anon
"""     

from django.utils.decorators import available_attrs
from django.utils.cache import add_never_cache_headers
from functools import wraps

def conditional_cache(view_func):
    """
    Checks the user and if it's authenticated pass it through never_cache.
    This version uses functools.wraps for the wrapper function.
    """ 
    @wraps(view_func, assigned=available_attrs(view_func))
    def _wrapped_view_func(request, *args, **kwargs):
        response = view_func(request, *args, **kwargs)
        if request.user.is_authenticated():
            add_never_cache_headers(response)
        return response
    return _wrapped_view_func

追加のデコレータの必要性を回避するための提案をいただければ幸いです。

ありがとう!

4

1 に答える 1

0

わかりました、「問題」が Django の User オブジェクトの遅延ロードによって引き起こされたことを確認しました。

それを確認するために、次のようなものをビューに追加しました。

test_var = "テキスト" + request.user

そして、str を SimpleLazyObject に連結できないというエラー メッセージが表示されました。この時点では、遅延読み込みロジックはまだ実際の User オブジェクトを取得していません。

遅延読み込みをバイパスして、認証されたユーザーに非キャッシュ ビューを返すには、いくつかのメソッドまたは属性にアクセスして、User オブジェクトで実際のクエリをトリガーする必要がありました。私はこれで終わりました。これが最も簡単な方法だと思います:

bypass_lazyload = request.user.is_authenticated()

私の conditional_cache デコレータはもう必要ありませんが、興味深い演習でした。

ビューでの作業が終了したら、テンプレートのいくつかのユーザー メソッドと属性にアクセスするので、これを行う必要はないかもしれませんが、何が起こっているのかを知ることは良いことです。

よろしく。

于 2012-08-23T13:21:02.597 に答える