naritoブログ

このブログはDjangoとBootstrap4で作成されました
ソースコード

Djangoで、キャッシュを使う

プログラミング関連 Django Python 約42日前
2018年1月14日2:49
Djangoでは、というより動的にページを作成する場合は殆どそうなのですが、

ブラウザからあるURLにアクセスする(HTTPリクエストを送る)

サーバー側のDjangoフレームワークに情報が渡され、ページを作成する(HTTPレスポンスとなるものを作る)

サーバーからブラウザにページ(HTTPレスポンス)を返し、ブラウザでそれを描画する

といった処理を行います。アクセスした段階で、やっとページを作成し始めるわけです。
Djangoのキャッシュ機能では、一度作成したページを何処かに保存しておき、次にそのページにアクセスされたらそれを返す、というのが基本です。
非常に豊富な機能があるのですが、今回は簡単に紹介します。


キャッシュをどこに保存するか、ファイルに保存することもできるし、Memcachedやデータベースを利用したり、メモリ上に保存することもできますが、今回はデータベースに保存することにします。そのための設定として、settings.pyに以下のように書いておきます。
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table',
    }
}


その後、コマンドを実行します。これで準備は完了です。
python3.6 manage.py createcachetable



まずは最も単純な、Djangoプロジェクト全体をキャッシュさせる方法です。
CommonMiddlewareの上下に追加します。
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.cache.UpdateCacheMiddleware',  # ここ
    'django.middleware.common.CommonMiddleware',  # ここ
    'django.middleware.cache.FetchFromCacheMiddleware',  # ここ
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]




次に、特定のビューだけキャッシュさせる方法です。上で書いたMIDDLEWAREは元に戻しておきましょう。views.pyで各ビューに設定することもできますが、urls.pyに定義することもできます。urls.pyに定義する方法のほうが、ビューの再利用がしやすくなるでしょう。60*15で、900秒、15分ですね。
urlpatterns = [
    path('', cache_page(60 * 15)(views.Top.as_view()), name='top'),
    # path('', views.Top.as_view(), name='top'),
]



キャッシュを一度削除したければ、manage.py shell等で、cache.clear()としましょう。
from django.core.cache import cache
cache.clear()

# 1行でコピペするならばこちら
from django.core.cache import cache;cache.clear()



例えば以下のようなビューをキャッシュする場合は注意してください。LoginRequiredMixinで、ログインユーザーしか見せないようなビューです。
class Top(LoginRequiredMixin, generic.TemplateView):
    template_name = 'app/top.html'



ログインユーザーでTopビューにアクセスしてしまうと、そのビューがキャッシュされます。URL単位でキャッシュを管理しており、今後そのURLに対してのアクセスは期限内であれば全てキャッシュが使われます。これが何を意味するかというと、ログインしていないユーザーであっても、キャッシュされたページが使われるということです。これの対策方法は幾つかありますが、そのようなビューはキャッシュしないのが最も簡単な方法です。


もう一つ、テンプレートに以下のような記述をしている場合も注意しましょう。最初に表示された内容でキャッシュされてしまい、管理者が管理者メニューを見れなくなるか、又は通常ユーザーが管理者メニューを見れるようになります。
{% if user.is_superuser %}
管理者用メニュー
{% else %}
通常メニュー
{% endif %}

他の表示...



こういった場合は、テンプレートでの部分的キャッシュが有効です。ビュー自体にキャッシュをしているとそちらが優先されるので、views.pyやurls.pyでキャッシュしていないことを確認しておきましょう。
{% if user.is_superuser %}
管理者用メニュー
{% else %}
通常メニュー
{% endif %}

{% load cache %}
{% cache 500 content %}
他の表示...
{% endcache %}