---
title: "Django のキャッシュフレームワーク"
version: 5.1
locale: ja
source: https://docs.djangoproject.com/ja/5.1/topics/cache/
canonical: https://djangodocs.dev/ja/5.1/topics/cache/
---
# Django のキャッシュフレームワーク

動的なウェブサイトの基本的なトレードオフは、ええと、それが動的であるということです。ユーザーがページをリクエストするたびに、ウェブサーバーはあらゆる種類の計算を行い (データベースのクエリから、テンプレートのレンダリングやビジネスロジックの実行まで)、サイトの訪問者が目にするページを作成します。これは、処理オーバーヘッドの観点から、ファイルシステムからファイルを読み取る標準的なサーバー構成よりもはるかに高コストです。

ほとんどの Web アプリケーションでは、このオーバーヘッドは大した問題ではありません。ほとんどの Web アプリケーションは `washingtonpost.com` や `slashdot.org` ではなく、そこそこのトラフィックがある小規模から中規模のサイトです。ただし、中トラフィックから高トラフィックのサイトでは、オーバーヘッドをできる限り削減することが不可欠です。

そこで登場するのがキャッシュです。

何かをキャッシュすることは、次回に計算を実行する必要がないように、高価な計算の結果を保存することです。以下に示すのは、動的に生成された Web ページでキャッシュがどのように機能するかを説明する疑似コードです。

```text
given a URL, try finding that page in the cache
if the page is in the cache:
    return the cached page
else:
    generate the page
    save the generated page in the cache (for next time)
    return the generated page
```

Django には、動的ページを保存できるロバストなキャッシュ システムが付属しているため、各リクエストごとに動的ページを計算する必要はありません。便宜上、Django は異なるレベルのキャッシュ粒度を提供しています。特定のビューの出力をキャッシュしたり、生成が難しい部分のみをキャッシュしたり、サイト全体をキャッシュできます。

Django は、 [Squid](http://www.squid-cache.org/) やブラウザベースのキャッシュなどの「ダウンストリーム」キャッシュでもうまく機能します。これらは、直接コントロールできないタイプのキャッシュですが、サイトのどの部分をどのようにキャッシュする必要があるかというヒントを (HTTP ヘッダー経由で) 提供できます。

> **See also**
>
> [キャッシュフレームワークの設計思想](/ja/5.1/misc/design-philosophies/#cache-design-philosophy) では、フレームワークの設計上の決定のいくつかについて説明します。

## キャッシュのセットアップ

キャッシュシステムにはちょっとした設定が必要です。つまり、キャッシュされたデータをどこに置くか、データベースか、ファイルシステムか、メモリに直接置くかを指定しなければなりません。これはキャッシュのパフォーマンスに影響する重要な決定です。

キャッシュの設定は設定ファイルの [`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) 設定にあります。ここでは、 [`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) で使用可能なすべての値について説明します。

### Memcached

[Memcached](https://memcached.org/) は完全にメモリベースのキャッシュ・サーバで、元々はLiveJournal.comの高負荷を処理するために開発され、その後Danga Interactiveによってオープンソース化されました。FacebookやWikipediaなどのサイトで使用され、データベースへのアクセスを減らし、サイトのパフォーマンスを劇的に向上させます。

Memcached はデーモンとして動作し、指定された量の RAM が割り当てられます。キャッシュにデータを追加、取得、削除するための高速なインターフェイスを提供するだけです。すべてのデータはメモリに直接保存されるので、データベースやファイルシステムの使用によるオーバーヘッドはありません。

Memcached 自体をインストールした後、Memcached バインディングをインストールする 必要があります。Python の Memcached バインディングはいくつかありますが、 Django がサポートしているのは [pylibmc](https://pypi.org/project/pylibmc/) と [pymemcache](https://pypi.org/project/pymemcache/) です。

Django で Memcached を使用する

- [`BACKEND`](/ja/5.1/ref/settings/#std-setting-CACHES-BACKEND) を `django.core.cache.backends.memcached.PyMemcacheCache` または `django.core.cache.backends.memcached.PyLibMCCache` (選択した memcached バインディングによる) に設定する
- [`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) を `ip:port` の値 (ここで、`ip` は Memcached デーモンの IP アドレス、`port` は Memcached が起動しているポート)、または、`unix:path` の値に設定する (ここで、`path` は Memcached Unix socket ファイルへのパス)。

次の例では、Memcached は localhost (127.0.0.1) port 11211 で起動していて、`pymemcache` バインディングを使用しています。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
        "LOCATION": "127.0.0.1:11211",
    }
}
```

次の例では、Memcached はローカルの Unix socket ファイル `/tmp/memcached.sock` 経由で利用可能であり、`pymemcache` バインディングを使用しています。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
        "LOCATION": "unix:/tmp/memcached.sock",
    }
}
```

Memcached の優れた機能の一つは、複数のサーバでキャッシュを共有できることです。つまり、複数のマシンで Memcached デーモンを実行することができ、各マシンでキャッシュの値を重複させることなく、 *単一の* キャッシュとして扱うことができます。この機能を利用するには、全てのサーバのアドレスを [`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) に、セミコロンまたはカンマ区切りの文字列、あるいはリストとして記述します。

このインスタンスでは、IP アドレス 172.19.26.240 と 172.19.26.242 で動作する Memcached インスタンスをポート 11211 で共有します:

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
        "LOCATION": [
            "172.19.26.240:11211",
            "172.19.26.242:11211",
        ],
    }
}
```

以下の例では、172.19.26.240 (port 11211)、172.19.26.242 (port 11212)、172.19.26.244 (port 11213) の IP アドレスで動作する Memcached インスタンスでキャッシュを共有しています:

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
        "LOCATION": [
            "172.19.26.240:11211",
            "172.19.26.242:11212",
            "172.19.26.244:11213",
        ],
    }
}
```

デフォルトでは、 `PyMemcacheCache` バックエンドは以下のオプションを設定します( [`OPTIONS`](/ja/5.1/ref/settings/#std-setting-CACHES-OPTIONS) で上書きできます):

```
"OPTIONS": {
    "allow_unicode_keys": True,
    "default_noreply": False,
    "serde": pymemcache.serde.pickle_serde,
}
```

Memcachedについての最後のポイントは、メモリベースのキャッシュには欠点があるということです。キャッシュされたデータはメモリに保存されるので、サーバーがクラッシュするとデータは失われます。メモリは永続的なデータ保存用ではないので、メモリベースのキャッシュを唯一のデータ保存用として使わないようにしましょう。明らかに、 Django のキャッシュバックエンドはどれも、永続的な保存には使うべきではありません。これらは全てキャッシュのためのソリューションであって、ストレージではありません。しかし、メモリベースのキャッシュは特に一時的なものであるため、 ここでに記載しておきます。

### Redis

[Redis](https://redis.io/) は、キャッシュに利用できるインメモリ データベースです。はじめに、Redis サーバーがローカルまたはリモートマシン上で起動している必要があります。

Redis サーバを設定した後、Redis の Python バインディングをインストールする必要があります。 [redis-py](https://pypi.org/project/redis/) は Django によってネイティブにサポートされているバインディングです。 [hiredis-py](https://pypi.org/project/hiredis/) パッケージも推奨のひとつです。

Redis をキャッシュ バックエンドとして Django で使用するには、次のようにします。

- [`BACKEND`](/ja/5.1/ref/settings/#std-setting-CACHES-BACKEND) を `django.core.cache.backends.redis.RedisCache` に設定する。
- [`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) を、適切なスキーマを使用して Redis インスタンスを指す URL に設定する。[利用可能なスキーマの詳細](https://redis-py.readthedocs.io/en/stable/connections.html#redis.connection.ConnectionPool.from_url) については、`redis-py` のドキュメントを参照してください。

たとえば、Redis が localhost (127.0.0.1) port 6379 で起動している場合は、次のように設定します。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
    }
}
```

Redis サーバーは認証で保護されていることがよくあります。ユーザー名とパスワードを提供するには、`LOCATION` 内に URL とともに追加します。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": "redis://username:password@127.0.0.1:6379",
    }
}
```

レプリケーション・モードで複数のRedisサーバーを設定している場合は、セミコロンまたはカンマ区切りの文字列、あるいはリストとしてサーバーを指定できます。複数のサーバーを使用している場合、書き込み操作は最初のサーバー（リーダー）で実行されます。読み取り操作は、ランダムに選ばれた他のサーバ（レプリカ）で実行されます:

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": [
            "redis://127.0.0.1:6379",  # leader
            "redis://127.0.0.1:6378",  # read-replica 1
            "redis://127.0.0.1:6377",  # read-replica 2
        ],
    }
}
```

### データベースのキャッシュ

Django はキャッシュデータをデータベース中に保存できます。この仕組みは、高速で適切にインデックス付けされたデータベースサーバーがある場合に、有効に機能します。

データベースのテーブルをキャッシュのバックエンドに使用する場合には、以下のように設定します。

- [`BACKEND`](/ja/5.1/ref/settings/#std-setting-CACHES-BACKEND) を `django.core.cache.backends.db.DatabaseCache` に設定する
- [`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) の `tablename` にデータベーステーブルの名前を設定します。この名前は、データベースで未使用かつ有効な名前であれば、自分が好きな名前で構いません。

この例では、キャッシュテーブルの名前を `my_cache_table` と設定しています。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.db.DatabaseCache",
        "LOCATION": "my_cache_table",
    }
}
```

他のキャッシュバックエンドとは異なり、データベースキャッシュはデータベースレベルでの期限切れエントリの自動間引き (culling) をサポートしていません。その代わり、 `add()` や `set()` 、 `touch()` が呼び出されるたびに、期限切れのキャッシュエントリが「間引き」されます。

#### キャッシュテーブルを作成する

データベース キャッシュを使用する前に、次のコマンドでキャッシュテーブルを必ず作成する必要があります。

```shell
python manage.py createcachetable
```

このコマンドにより、データベース内に1つのテーブルが作成され、Django のデータベースキャッシュシステムに必要な適切なフォーマットが生成されます。テーブルの名前は [`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) が使用されます。

複数のデータベースキャッシュが使用される場合、[`createcachetable`](/ja/5.1/ref/django-admin/#django-admin-createcachetable) は1つのキャッシュごとに、対応する1つのテーブルを作成します。

複数のデータベースを使用する場合、[`createcachetable`](/ja/5.1/ref/django-admin/#django-admin-createcachetable) は、データベースのルートの `allow_migrate()` メソッド (以下を参照) を監視します。

[`migrate`](/ja/5.1/ref/django-admin/#django-admin-migrate) と同様に、[`createcachetable`](/ja/5.1/ref/django-admin/#django-admin-createcachetable) は既に存在する既存のテーブルにたいしては手を触れません。存在しないテーブルのみを生成します。

実行される予定の SQL を実行せずに表示するためには、[`createcachetable --dry-run`](/ja/5.1/ref/django-admin/#cmdoption-createcachetable-dry-run) オプションを使用します。

#### 複数のデータベース

複数のデータベースでデータベースキャッシュを使用する場合、データベースキャッシュテーブルのためにルーティングの指示も設定する必要があります。ルーティングの目的で、データベースキャッシュテーブルは、`django_cache` という名前のアプリケーションに `CacheEntry` という名前のモデルとして表示されます。このモデルはモデルキャッシュには表示されませんが、ルーティングの目的でモデルの詳細情報を使用できます。

たとえば、以下のルーターはすべてのキャッシュの読み込み操作を `cache_replica` に転送し、すべての書き込み操作を `cache_primary` に転送します。キャッシュテーブルは `cache_primary` にだけ同期されます。

```
class CacheRouter:
    """A router to control all database cache operations"""

    def db_for_read(self, model, **hints):
        "All cache read operations go to the replica"
        if model._meta.app_label == "django_cache":
            return "cache_replica"
        return None

    def db_for_write(self, model, **hints):
        "All cache write operations go to primary"
        if model._meta.app_label == "django_cache":
            return "cache_primary"
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        "Only install the cache model on primary"
        if app_label == "django_cache":
            return db == "cache_primary"
        return None
```

データベースキャッシュモデルに対してルーティングの方向を指定しなかった場合、キャッシュバックエンドは `default` データベースを使用します。

そして、データベースキャッシュバックエンドを使用しなかった場合には、データベースキャッシュモデルに対してデータベースルーティングの指示を提供することについて心配する必要はありません。

### ファイルシステムのキャッシュ

ファイルベースのバックエンドは、各キャッシュの値を独立したファイルとしてシリアライズして保存します。このバックエンドを使用するには、[`BACKEND`](/ja/5.1/ref/settings/#std-setting-CACHES-BACKEND) を `"django.core.cache.backends.filebased.FileBasedCache"` に設定して、[`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) を適切なディレクトリに設定します。たとえば、キャッシュデータを `/var/tmp/django_cache` に保存するには、次の設定を使ってください。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
        "LOCATION": "/var/tmp/django_cache",
    }
}
```

Windows では、次のようにドライブ文字をパスの最初に付けてください。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
        "LOCATION": "c:/foo/bar",
    }
}
```

ディレクトリのパスは絶対パスである必要があります。つまり、ファイルシステムのルートから始まる必要があります。設定の最後にスラッシュを置くかどうかは関係ありません。

この設定が指すディレクトリは、存在して読み込みと書き込みが可能であるか、または、ウェブサーバーを実行しているシステムユーザーによって作成可能であることを確認してください。上の例を続けると、もしサーバーが `apache` ユーザーで実行されているなら、`/var/tmp/django_cache` が存在して `apache` ユーザーにより読み書き可能であるか、このディレクトリを `apache` ユーザーが作成できることを確認してください。

> **Warning**
>
> キャッシュの [`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) が、[`MEDIA_ROOT`](/ja/5.1/ref/settings/#std-setting-MEDIA_ROOT)、[`STATIC_ROOT`](/ja/5.1/ref/settings/#std-setting-STATIC_ROOT)、[`STATICFILES_FINDERS`](/ja/5.1/ref/settings/#std-setting-STATICFILES_FINDERS) のいずれかの配下に含まれていると、機密データが漏洩してしまう可能性があります。
>
> キャッシュファイルへのアクセスを獲得した攻撃者は、HTML コンテンツを改竄できるだけでなく、データが [`pickle`](https://docs.python.org/3/library/pickle.html#module-pickle) を使用してシリアライズされているため、任意のコードのリモート実行までできてしまいます。

> **Warning**
>
> ファイルシステムキャッシュは、大量のファイルを保存すると低速になってしまう可能性があります。この問題に遭遇したときは、別のキャッシュメカニズムの使用を検討してください。[FileBasedCache](https://github.com/django/django/blob/stable/5.1.x/django/core/cache/backends/filebased.py) をサブクラス化して、淘汰戦略を改善することもできます。

### ローカルメモリのキャッシュ

設定ファイルに他のキャッシュが指定されていない場合、これがデフォルトのキャッシュとなります。インメモリキャッシュの速度の利点が欲しいが、Memcached を扱うのが難しい場合は、 ローカルメモリキャッシュバックエンドを検討してください。このキャッシュはプロセス単位 (後述) で、スレッドセーフです。これを使うには、 [`BACKEND`](/ja/5.1/ref/settings/#std-setting-CACHES-BACKEND) を `"django.core.cache.backends.locmem.LocMemCache"` に設定します。たとえば

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
        "LOCATION": "unique-snowflake",
    }
}
```

キャッシュの [`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) は個々のメモリストアを識別するために使用されます。もし `locmem` キャッシュが1つしかない場合は [`LOCATION`](/ja/5.1/ref/settings/#std-setting-CACHES-LOCATION) を省略できます。しかし、複数のローカルメモリーキャッシュがある場合は、それらを区別するために少なくとも1つに名前を割り当てる必要があります。

キャッシュは LRU (least-recently-used) 淘汰戦略 (culling strategy) を使用します。

各プロセスはそれ自身のプライベートキャッシュインスタンスを持つことに注意してください。このことは、ローカル・メモリ・キャッシュが特にメモリ効率に優れているわけではないことを意味します。そのため、おそらく本番環境には良い選択ではありません。開発環境には適しています。

### ダミーキャッシュ（開発用）

最後に、 Django には実際にはキャッシュしない「ダミー」キャッシュが付属しています。何もせずにキャッシュインターフェースを実装しているだけです。

これは、様々な場所で重量級のキャッシュを使用する本番サイトと、開発/テスト用に、キャッシュを行わず、コード変更も最小限に留めたい環境がある場合に便利です。ダミーキャッシュをアクティブにするには、[`BACKEND`](/ja/5.1/ref/settings/#std-setting-CACHES-BACKEND) を以下のように設定します。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.dummy.DummyCache",
    }
}
```

### 独自のキャッシュバックエンドを使う

Django は「箱から出してすぐに」多くのキャッシュバックエンドをサポートしていますが、カスタマイズ したキャッシュバックエンドを使いたいこともあるでしょう。Django で外部のキャッシュバックエンドを使用するには、下記のように、 [`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) 設定の [`BACKEND`](/ja/5.1/ref/settings/#std-setting-CACHES-BACKEND) に Python のインポートパスを使用します:

```
CACHES = {
    "default": {
        "BACKEND": "path.to.backend",
    }
}
```

独自のバックエンドを構築する場合は、標準のキャッシュバックエンドをリファレンス実装として使うことができます。コードは Django ソースの [django/core/cache/backends/](https://github.com/django/django/blob/stable/5.1.x/django/core/cache/backends/) ディレクトリにあります。

注記：ホストがサポートしていないなど、やむを得ない理由がない限り、Django に付属しているキャッシュバックエンドを使用するべきです。それらは十分にテストされており、よくドキュメント化されています。

### キャッシュ引数

それぞれのキャッシュバックエンドはキャッシュの動作を制御するために追加の引数を指定できます。これらの引数は [`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) 設定の追加キーとして提供されます。有効な引数は以下の通りです:

- [`TIMEOUT`](/ja/5.1/ref/settings/#std-setting-CACHES-TIMEOUT): キャッシュに使用するデフォルトのタイムアウトを秒単位で指定します。この引数のデフォルトは `300` 秒（5分）です。 `TIMEOUT` に `None` を指定することで、デフォルトではキャッシュキーの有効期限が切れません。値を `0` にすると、キーはすぐに期限切れになります（事実上 "キャッシュしない"）。
- [`OPTIONS`](/ja/5.1/ref/settings/#std-setting-CACHES-OPTIONS): キャッシュバックエンドに渡すオプション。有効なオプションのリストはバックエンドによって異なり、サードパーティライブラリにバックされたキャッシュバックエンドはそのオプションを直接キャッシュライブラリに渡します。

  独自の淘汰戦略 (culling strategy) を実装しているキャッシュバックエンド (`locmem`、`filesystem`、`database` バックエンド) では、以下のオプションが有効です:

  - `MAX_ENTRIES`: 古い値が削除されるまでにキャッシュに保存できる最大エントリ数。この引数のデフォルトは `300` です。
  - `CULL_FREQUENCY`: `MAX_ENTRIES` に達したときに間引き (cull) されるエントリの割合。実際の割合は `1 / CULL_FREQUENCY` なので、 `CULL_FREQUENCY` を `2` に設定すると、 `MAX_ENTRIES` に達したときにエントリの半分をカリングします。この引数は整数で、デフォルトは `3` です。

    `CULL_FREQUENCY` に `0` という値を指定すると、 `MAX_ENTRIES` に達したときにキャッシュ全体がダンプされます。一部のバックエンド (特に `database`) では、キャッシュミスが増える代わりにカリング（間引き）が非常に速くなります。

  Memcached と Redis のバックエンドは、クライアントの動作をより高度に制御できるように、クライアントのコンストラクタにキーワード引数として [`OPTIONS`](/ja/5.1/ref/settings/#std-setting-CACHES-OPTIONS) の内容を渡します。使用例は以下を参照してください。
- [`KEY_PREFIX`](/ja/5.1/ref/settings/#std-setting-CACHES-KEY_PREFIX): Django サーバが使用する全てのキャッシュキーに自動的に含まれる文字列です（デフォルトでは先頭に付加されます）。

  詳細は [キャッシュのドキュメント](#cache-key-prefixing) を参照してください。
- [`VERSION`](/ja/5.1/ref/settings/#std-setting-CACHES-VERSION): Django サーバが生成するキャッシュキーのデフォルトのバージョン番号。

  詳細は [キャッシュのドキュメント](#cache-versioning) を参照してください。
- [`KEY_FUNCTION`](/ja/5.1/ref/settings/#std-setting-CACHES-KEY_FUNCTION) プレフィックス、バージョン、およびキーを最終的なキャッシュ・キーに合成する方法を定義する関数へのドット区切りパスを含む文字列。

  詳細は [キャッシュのドキュメント](#cache-key-transformation) を参照してください。

この例では、ファイルシステム・バックエンドをタイムアウト60秒、最大容量1000アイテムで設定しています。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
        "LOCATION": "/var/tmp/django_cache",
        "TIMEOUT": 60,
        "OPTIONS": {"MAX_ENTRIES": 1000},
    }
}
```

以下は、`pylibmc` ベースのバックエンドをバイナリプロトコル、SASL認証、および `ketama` 挙動モードを有効に設定する例です。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.memcached.PyLibMCCache",
        "LOCATION": "127.0.0.1:11211",
        "OPTIONS": {
            "binary": True,
            "username": "user",
            "password": "pass",
            "behaviors": {
                "ketama": True,
            },
        },
    }
}
```

以下は `pymemcache` ベースのバックエンドの設定例です。クライアントのプーリングを有効にし (クライアントの接続を維持することでパフォーマンスを向上させることができます)、memcache/ネットワークのエラーをキャッシュミスとして扱い、接続ソケットに `TCP_NODELAY` フラグを設定します。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
        "LOCATION": "127.0.0.1:11211",
        "OPTIONS": {
            "no_delay": True,
            "ignore_exc": True,
            "max_pool_size": 4,
            "use_pooling": True,
        },
    }
}
```

以下は、`redis` を使用したバックエンドの設定例です。この設定では、データベース `10` を選択し（デフォルトでは Redis は16個の論理データベースを提供しています）、カスタムの [connection pool class](https://github.com/redis/redis-py#connection-pools) を設定します（デフォルトでは `redis.ConnectionPool` が使用されます）。

```
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "db": "10",
            "pool_class": "redis.BlockingConnectionPool",
        },
    }
}
```

## サイトごとのキャッシュ

キャッシュを設定したら、キャッシュを使う最も簡単な方法はサイト全体をキャッシュすることです。この例のように、 `'django.middleware.cache.UpdateCacheMiddleware'` と `'django.middleware.cache.FetchFromCacheMiddleware'` を [`MIDDLEWARE`](/ja/5.1/ref/settings/#std-setting-MIDDLEWARE) 設定に追加する必要があります:

```
MIDDLEWARE = [
    "django.middleware.cache.UpdateCacheMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.cache.FetchFromCacheMiddleware",
]
```

> **Note**
>
> いいえ、これは typo ではありません。"update" ミドルウェアはリストの最初に、"fetch" ミドルウェアはリストの最後になければなりません。詳細は少し曖昧ですが、全容を知りたい方は下記の [Order of MIDDLEWARE](#order-of-middleware) を参照してください。

次に、以下の必要な設定を Django 設定ファイルに追加します:

- [`CACHE_MIDDLEWARE_ALIAS`](/ja/5.1/ref/settings/#std-setting-CACHE_MIDDLEWARE_ALIAS) -- ストレージに使用するキャッシュのエイリアス。
- [`CACHE_MIDDLEWARE_SECONDS`](/ja/5.1/ref/settings/#std-setting-CACHE_MIDDLEWARE_SECONDS) -- 各ページがキャッシュされるべき秒数を整数で指定します。
- [`CACHE_MIDDLEWARE_KEY_PREFIX`](/ja/5.1/ref/settings/#std-setting-CACHE_MIDDLEWARE_KEY_PREFIX) -- キャッシュが同じ Django インストールを使っている複数のサイトで共有され ている場合、キーの衝突を防ぐために、サイトの名前か、この Django インスタンスに固有な文字列を指定します。気にしないなら空文字列を使いましょう。

`FetchFromCacheMiddleware` はリクエストヘッダとレスポンスヘッダが許す限り、ステータス 200 の GET と HEAD レスポンスをキャッシュします。異なるクエリパラメータを持つ同じURLへのリクエストに対するレスポンスはユニークなページとみなされ、別々にキャッシュされます。このミドルウェアは、HEADリクエストが、対応するGETリクエストと同じレスポンスヘッダーで応答されることを期待します。その場合、HEADリクエストに対してキャッシュされたGETレスポンスを返すことができます。

さらに、`UpdateCacheMiddleware` は [ダウンストリームキャッシュ](#downstream-caches) に影響を与えるいくつかのヘッダを [`HttpResponse`](/ja/5.1/ref/request-response/#django.http.HttpResponse) に自動的に設定します:

- `Expires` ヘッダーに現在の日時と定義された [`CACHE_MIDDLEWARE_SECONDS`](/ja/5.1/ref/settings/#std-setting-CACHE_MIDDLEWARE_SECONDS) をセットします。
- `Cache-Control` ヘッダにページの最大寿命をセットします -- ここでも [`CACHE_MIDDLEWARE_SECONDS`](/ja/5.1/ref/settings/#std-setting-CACHE_MIDDLEWARE_SECONDS) 設定を使用します。

ミドルウェアについては [ミドルウェア (Middleware)](/ja/5.1/topics/http/middleware/) を参照してください。

ビューがキャッシュの有効期限を設定している場合 (つまり、ヘッダの `Cache-Control` に `max-age` セクションがある場合) は、 [`CACHE_MIDDLEWARE_SECONDS`](/ja/5.1/ref/settings/#std-setting-CACHE_MIDDLEWARE_SECONDS) ではなく、有効期限までページがキャッシュされます。`django.views.decorators.cache` のデコレータを使用すると、ビューの有効期限を簡単に設定 ([`cache_control()`](/ja/5.1/topics/http/decorators/#django.views.decorators.cache.cache_control) デコレータを使用) したり、ビューのキャッシュを無効にしたり ([`never_cache()`](/ja/5.1/topics/http/decorators/#django.views.decorators.cache.never_cache) デコレータを使用) することができます。これらのデコレータについての詳細は、 [他のヘッダを使用する](#controlling-cache-using-other-headers) セクションを参照してください。

[`USE_I18N`](/ja/5.1/ref/settings/#std-setting-USE_I18N) が `True` に設定されている場合、生成されたキャッシュキーにアクティブな [言語](/ja/5.1/topics/i18n/#term-language-code) の名前が含まれるようになります。 [Django はどうやって言語の優先順位を検出するのか？](/ja/5.1/topics/i18n/translation/#how-django-discovers-language-preference) も参照してください。これにより、自分でキャッシュキーを作成する必要なく、複数言語のサイトを簡単にキャッシュできるようになります。

[`USE_TZ`](/ja/5.1/ref/settings/#std-setting-USE_TZ) が `True` に設定されている場合、キャッシュキーには [カレントタイムゾーン](/ja/5.1/topics/i18n/timezones/#default-current-time-zone) も含まれます。

## ビューごとのキャッシュ

#### `django.views.decorators.cache.cache_page(timeout, * (Keyword-only parameters separator (PEP 3102)), cache=None, key_prefix=None)`

キャッシュフレームワークをより細かい単位で使用するには、個別のビューの出力をキャッシュする方法があります。`django.views.decorators.cache` は `cache_page` デコレーターを定義しており、これを使うとビューのレスポンスが自動的にキャッシュされるようになります。

```
from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request): ...
```

`cache_page` はキャッシュのタイムアウトを秒数で指定する1つの引数を取ります。上の例では、`my_view()`  ビューの結果が15分間キャッシュされます。(ここでリーダビリティのために `60 * 15` と書いていることに注意してください。`60 * 15` は `900` つまり15分×60秒と評価されます。)

`cache_page` で設定されたキャッシュのタイムアウトは、`Cache-Control` ヘッダの `max-age` ディレクティブよりも優先されます。

サイトごとのキャッシュと同様に、ビューごとのキャッシュは URL でキーが区別されます。もし複数の URL が同じビューを指した場合、各 URL が別にキャッシュされます。`my_view` の例を続けて、URLconf が次のようになっているとします。

```
urlpatterns = [
    path("foo/<int:code>/", my_view),
]
```

このとき、`/foo/1/` と `/foo/23/` へのリクエストは別々にキャッシュされます。しかし、特定の URL (たとえば、`/foo/23/`) が一度リクエストされると、その URL への続くリクエストにはキャッシュが使われます。

`cache_page` はオプション引数の `cache` を取ることもできます。これを使うと、ビューの結果をキャッシュするときに、デコレータに ([`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) 設定から) 特定のキャッシュを使うように指示できます。デフォルトでは、`default` キャッシュが使われますが、使いたいキャッシュはどれでも指定できます。

```
@cache_page(60 * 15, cache="special_cache")
def my_view(request): ...
```

また、ビューごとにキャッシュプレフィックスを上書きすることもできます。 `cache_page` はオプションのキーワード引数 `key_prefix` を取ります。これはミドルウェアの [`CACHE_MIDDLEWARE_KEY_PREFIX`](/ja/5.1/ref/settings/#std-setting-CACHE_MIDDLEWARE_KEY_PREFIX) 設定と同じように動作します。 次のように使用します:

```
@cache_page(60 * 15, key_prefix="site1")
def my_view(request): ...
```

`key_prefix` 引数と `cache` 引数は同時に指定できます。 `key_prefix` 引数と [`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) で指定した [`KEY_PREFIX`](/ja/5.1/ref/settings/#std-setting-CACHES-KEY_PREFIX) は連結されます。

さらに、 `cache_page` は自動的にレスポンスに `Cache-Control` と `Expires` ヘッダを設定します。このヘッダは [ダウンストリームキャッシュ](#downstream-caches) に影響を与えます。

### ビューごとのキャッシュを URLconf で指定する

前のセクションの例では、 `cache_page` が `my_view` 関数を変更するため、ビューがキャッシュされることをハードコードしていました。この方法では、ビューをキャッシュシステムに結合することになり、いくつかの理由から理想的ではありません。例えば、キャッシュのない別のサイトでビュー関数を再利用したい場合や、キャッシュされずにビューを使いたい人にビューを配布したい場合などです。このような問題の解決策は、ビュー関数そのものではなく URLconf でビューごとのキャッシュを指定することです。

URLconf でビュー関数を参照するときに `cache_page` でラップすることで、これを実現できます。以下は以前の古い URLconf です。

```
urlpatterns = [
    path("foo/<int:code>/", my_view),
]
```

以下は `my_view` を `cache_page` でラップしたものです。

```
from django.views.decorators.cache import cache_page

urlpatterns = [
    path("foo/<int:code>/", cache_page(60 * 15)(my_view)),
]
```

## テンプレートフラグメントのキャッシュ

さらにコントロールしたい場合は、 `cache` テンプレートタグを使ってテンプレートの断片をキャッシュすることもできます。テンプレートからこのタグにアクセスするには、テンプレートの先頭付近に `{% load cache %}` を記述します。

テンプレートタグ `{% cache %}` は指定した時間だけブロックの内容をキャッシュします。少なくとも2つの引数を取ります。秒単位のキャッシュタイムアウトと、キャッシュフラグメントに与える名前です。timeout が `None` の場合、フラグメントは永遠にキャッシュされます。名前はそのまま使用されるので、変数は使えません。次に例を示します。

```html+django
{% load cache %}
{% cache 500 sidebar %}
    .. sidebar ..
{% endcache %}
```

フラグメントの内部に現れる動的なデータに応じて、フラグメントの複数のコピーをキャッシュしたい場合があります。たとえば、先ほどの例で使用したサイドバーを、サイトのすべてのユーザーに対して個別にキャッシュしたいとします。これを行うには、キャッシュフラグメントを一意に識別するために、フィルタの有無にかかわらず、1つ以上の追加の引数を `{% cache %}` テンプレートタグに渡します。

```html+django
{% load cache %}
{% cache 500 sidebar request.user.username %}
    .. sidebar for logged in user ..
{% endcache %}
```

[`USE_I18N`](/ja/5.1/ref/settings/#std-setting-USE_I18N) が `True` に設定されている場合、サイトごとのミドルウェアキャッシュは [アクティブな言語](#i18n-cache-key) を尊重します。テンプレートタグの `cache` では [翻訳固有の変数](/ja/5.1/topics/i18n/translation/#template-translation-vars) を使えば同じ結果が得られます:

```html+django
{% load i18n %}
{% load cache %}

{% get_current_language as LANGUAGE_CODE %}

{% cache 600 welcome LANGUAGE_CODE %}
    {% translate "Welcome to example.com" %}
{% endcache %}
```

テンプレート変数が整数値に解決されるなら、キャッシュタイムアウトにはテンプレート変数が使えます。例えば、テンプレート変数 `my_timeout` が値 `600` に指定されている場合、以下の2つの例は等価です:

```html+django
{% cache 600 sidebar %} ... {% endcache %}
{% cache my_timeout sidebar %} ... {% endcache %}
```

この機能はテンプレート内での繰り返しを避けるのに便利です。1つの変数にタイムアウトを指定し、その値を再利用できます。

デフォルトでは、キャッシュタグは "template\_fragments" というキャッシュを使用しようとします。そのようなキャッシュが存在しない場合は、デフォルトのキャッシュを使用します。キーワード引数 `using` で、使用する別のキャッシュバックエンドを選択できます。

```html+django
{% cache 300 local-thing ...  using="localcache" %}
```

設定されていないキャッシュ名を指定することはエラーとみなされます。

#### `django.core.cache.utils.make_template_fragment_key(fragment_name, vary_on=None)`

キャッシュされたフラグメントに使用されるキャッシュキーを取得したい場合は、 `make_template_fragment_key` を使用します。フラグメント名 `fragment_name` は `cache` テンプレートタグの2番目の引数と同じです。この関数は、キャッシュされたアイテムを無効にしたり上書きしたりする場合などに便利です:

```pycon
>>> from django.core.cache import cache
>>> from django.core.cache.utils import make_template_fragment_key
# cache key for {% cache 500 sidebar username %}
>>> key = make_template_fragment_key("sidebar", [username])
>>> cache.delete(key)  # invalidates cached template fragment
True
```

## 低レベルキャッシュ API

レンダリングされたページ全体をキャッシュしてもあまりメリットがないこともありますし、実際、過剰なキャッシュはかえって不便です。

たとえば、あなたのサイトには、結果が複数の高コストなクエリに依存し、その結果が異なる間隔で変化するビューが含まれているとします。この場合、サイト単位やビュー単位のキャッシュ戦略が提供するフルページキャッシュを使うのは理想的ではありません。なぜなら、結果全体をキャッシュしたいとは思わないでしょうが(データの一部が頻繁に変更されるからです)、めったに変更されない結果はキャッシュしたいからです。

このような場合のために、 Django は低レベルのキャッシュ API を公開しています。この API を使えば、好きなレベルでオブジェクトをキャッシュに保存できます。 安全に pickle 化できる Python オブジェクトなら何でもキャッシュできます: 文字列、辞書、モデルオブジェクトのリストなど。(ほとんどの一般的なPythonオブジェクトはpickle化できます。pickle化についての詳細はPythonのドキュメントを参照してください)。

### キャッシュへのアクセス

#### `django.core.cache.caches`

[`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) 設定で設定したキャッシュには、 `django.core.cache.caches` という Dict のようなオブジェクトでアクセスできます。同じスレッドで同じエイリアスを繰り返しリクエストすると、同じオブジェクトが返されます。

```pycon
>>> from django.core.cache import caches
>>> cache1 = caches["myalias"]
>>> cache2 = caches["myalias"]
>>> cache1 is cache2
True
```

指定したキーが存在しない場合、 `InvalidCacheBackendError` が発生します。

スレッドセーフを実現するために、キャッシュバックエンドの異なるインスタンスがスレッドごとに返されます。

#### `django.core.cache.cache`

ショートカットとして、デフォルトのキャッシュは `django.core.cache.cache` で利用できます:

```pycon
>>> from django.core.cache import cache
```

このオブジェクトは `caches['default']` と等価です。

### 基本的な使用法

基本的なインターフェイスは、次のようになります。

#### `cache.set(key, value, timeout=DEFAULT_TIMEOUT, version=None)`

```pycon
>>> cache.set("my_key", "hello, world!", 30)
```

#### `cache.get(key, default=None, version=None)`

```pycon
>>> cache.get("my_key")
'hello, world!'
```

`key` には `str` を指定し、 `value` には任意の Python オブジェクトを指定します。

引数の `timeout` はオプションで、デフォルトは [`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) 設定 (上記で説明) にある適切なバックエンドの `timeout` 引数です。これはキャッシュに保存される秒数です。 `timeout` に `None` を渡すと、値は永遠にキャッシュされます。 `timeout` に `0` を渡すと、値はキャッシュされません。

オブジェクトがキャッシュに存在しない場合、 `cache.get()` は `None` を返します:

```pycon
>>> # Wait 30 seconds for 'my_key' to expire...
>>> cache.get("my_key")
None
```

オブジェクトがキャッシュに存在するかどうかを判断する必要があり、リテラル値 `None` を保存した場合は、デフォルトとして sentinel オブジェクトを使用します:

```pycon
>>> sentinel = object()
>>> cache.get("my_key", sentinel) is sentinel
False
>>> # Wait 30 seconds for 'my_key' to expire...
>>> cache.get("my_key", sentinel) is sentinel
True
```

`cache.get()` は `default` 引数を取ることができます。これは、オブジェクトがキャッシュに存在しない場合に返す値を指定します:

```pycon
>>> cache.get("my_key", "has expired")
'has expired'
```

#### `cache.add(key, value, timeout=DEFAULT_TIMEOUT, version=None)`

キーがまだ存在しない場合にのみキーを追加するには、 `add()` メソッドを使用します。このメソッドは `set()` と同じパラメータを受け取りますが、指定したキーがすでに存在する場合はキャッシュを更新しようとしません:

```pycon
>>> cache.set("add_key", "Initial value")
>>> cache.add("add_key", "New value")
>>> cache.get("add_key")
'Initial value'
```

もし `add()` が値をキャッシュに保存したかどうかを知りたい場合は、戻り値をチェックできます。値が保存されていれば `True` を返し、そうでなければ `False` を返します。

#### `cache.get_or_set(key, default, timeout=DEFAULT_TIMEOUT, version=None)`

キーの値を取得したり、そのキーがキャッシュにない場合に値を設定したい場合は、 `get_or_set()` メソッドが使えます。これは `get()` と同じパラメータを受け取りますが、そのキーのデフォルトの戻り値が設定されます:

```pycon
>>> cache.get("my_new_key")  # returns None
>>> cache.get_or_set("my_new_key", "my new value", 100)
'my new value'
```

また、任意の呼び出し可能オブジェクトを *デフォルト* 値として渡すこともできます:

```pycon
>>> import datetime
>>> cache.get_or_set("some-timestamp-key", datetime.datetime.now)
datetime.datetime(2014, 12, 11, 0, 15, 49, 457920)
```

#### `cache.get_many(keys, version=None)`

一度だけキャッシュをヒットする `get_many()` インターフェースもあります。 `get_many()` は、キャッシュに実際に存在する (そして有効期限が切れていない) キーをすべて含む辞書を返します:

```pycon
>>> cache.set("a", 1)
>>> cache.set("b", 2)
>>> cache.set("c", 3)
>>> cache.get_many(["a", "b", "c"])
{'a': 1, 'b': 2, 'c': 3}
```

#### `cache.set_many(dict, timeout)`

より効率的に複数の値を指定するには、 `set_many()` を使用してキーと値のペアの辞書を渡します:

```pycon
>>> cache.set_many({"a": 1, "b": 2, "c": 3})
>>> cache.get_many(["a", "b", "c"])
{'a': 1, 'b': 2, 'c': 3}
```

`cache.set()` と同様に、 `set_many()` はオプションの `timeout` パラメータを受け取ります。

サポートされているバックエンド (memcached) では、 `set_many()` は挿入に失敗したキーのリストを返します。

#### `cache.delete(key, version=None)`

`delete()` で明示的にキーを削除することで、特定のオブジェクトのキャッシュをクリアできます:

```pycon
>>> cache.delete("a")
True
```

`delete()` はキーの削除に成功すると `True` を返し、失敗すると `False` を返します。

#### `cache.delete_many(keys, version=None)`

一度にたくさんのキーをクリアしたい場合は、 `delete_many()` にクリアしたいキーのリストを渡します:

```pycon
>>> cache.delete_many(["a", "b", "c"])
```

#### `cache.clear()`

最後に、キャッシュ内のすべてのキーを削除したい場合は、`cache.clear()` を使用してください。ただし、この操作には注意が必要です。`clear()` はアプリケーションによって設定されたキーだけでなく、 **キャッシュ内のすべて** を削除します。

```pycon
>>> cache.clear()
```

#### `cache.touch(key, timeout=DEFAULT_TIMEOUT, version=None)`

`cache.touch()` はキーの有効期限を設定します。例えば、キーの有効期限を10秒後に更新する場合:

```pycon
>>> cache.touch("a", 10)
True
```

他のメソッドと同様に、 `timeout` 引数はオプションで、デフォルトは [`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) 設定の適切なバックエンドの `TIMEOUT` オプションです。

`touch()` はキーが正しく touch された場合は `True` を返し、そうでない場合は `False` を返します。

#### `cache.incr(key, delta=1, version=None)`

#### `cache.decr(key, delta=1, version=None)`

`incr()` メソッドまたは `decr()` メソッドを使用して、既に存在するキーをインクリメント/デクリメントすることもできます。デフォルトでは、既存のキャッシュの値が 1 だけインクリメント/デクリメントされます。インクリメント/デクリメントの呼び出しに引数を指定することで、1以外のインクリメント/デクリメント値を指定できます。存在しないキャッシュ・キーをインクリメントまたはデクリメントしようとすると、ValueError が発生します:

```pycon
>>> cache.set("num", 1)
>>> cache.incr("num")
2
>>> cache.incr("num", 10)
12
>>> cache.decr("num")
11
>>> cache.decr("num", 5)
6
```

> **Note**
>
> `incr()`/`decr()` メソッドはアトミックであることは保証されていません。アトミックなインクリメント/デクリメントをサポートしているバックエンド (特に memcached バックエンド) では、インクリメントとデクリメントの操作はアトミックに行われます。しかし、バックエンドがネイティブにインクリメント/デクリメント操作を提供していない場合は、取得/更新の2段階を使って実装されます。

#### `cache.close()`

キャッシュバックエンドに実装されていれば、 `close()` でキャッシュへの接続を閉じることができます。

```pycon
>>> cache.close()
```

> **Note**
>
> `close` メソッドを実装していないキャッシュでは、このメソッドは何もしません。

> **Note**
>
> メソッドの非同期バージョンは、ベースとなるメソッドに `a` で始まるプレフィックスが付けられています。例えば、 `cache.aadd()` や `cache.adelete_many()` です。詳細については [Asynchronous support](#id16) を参照してください。

### キャッシュ キーにプレフィックスを付ける

サーバ間でキャッシュインスタンスを共有している場合、あるいは本番環境と開発環境の間でキャッシュインスタンスを共有している場合、あるサーバでキャッシュされたデータが別のサーバで使用される可能性があります。キャッシュされたデータのフォーマットがサーバ間で異なる場合、非常に診断が難しい問題につながる可能性があります。

これを防ぐために、 Django はサーバが使う全てのキャッシュキーの前にプレフィックスを付ける機能を提供します。特定のキャッシュキーが保存または取得されると、 Django は自動的に [`KEY_PREFIX`](/ja/5.1/ref/settings/#std-setting-CACHES-KEY_PREFIX) キャッシュ設定の値をキャッシュキーの先頭に付加します。

各 Django インスタンスに異なる [`KEY_PREFIX`](/ja/5.1/ref/settings/#std-setting-CACHES-KEY_PREFIX) を持たせることで、キャッシュ値が衝突しないようにできます。

### キャッシュのバージョン管理

キャッシュされた値を使用する実行中のコードを変更する場合、既存のキャッシュされた値を消去する必要があるかもしれません。これを行う最も簡単な方法はキャッシュ全体を削除することですが、まだ有効で有用なキャッシュ値を失うことになります。

Django は個々のキャッシュ値をターゲットにする、より良い方法を提供します。Django のキャッシュフレームワークには、 [`VERSION`](/ja/5.1/ref/settings/#std-setting-CACHES-VERSION) キャッシュ設定で指定できる、システム全体のバージョン識別子があります。この設定の値は、自動的にキャッシュ・プレフィックスとユーザが指定したキャッシュ・キーと組み合わされ、最終的なキャッシュ・キーが得られます。

デフォルトでは、どのようなキャッシュキーのリクエストも自動的にサイトのデフォルトのキャッシュキーのバージョンを含みます。しかし、基本的なキャッシュ関数には `version` 引数が含まれているので、特定のキャッシュキーのバージョンを指定できます。たとえば:

```pycon
>>> # Set version 2 of a cache key
>>> cache.set("my_key", "hello world!", version=2)
>>> # Get the default version (assuming version=1)
>>> cache.get("my_key")
None
>>> # Get version 2 of the same key
>>> cache.get("my_key", version=2)
'hello world!'
```

特定のキーのバージョンは `incr_version()` メソッドと `decr_version()` メソッドで増減できます。これにより、特定のキーのバージョンを新しいものに変更できます。先ほどの例の続きで、下記のようにします:

```pycon
>>> # Increment the version of 'my_key'
>>> cache.incr_version("my_key")
>>> # The default version still isn't available
>>> cache.get("my_key")
None
# Version 2 isn't available, either
>>> cache.get("my_key", version=2)
None
>>> # But version 3 *is* available
>>> cache.get("my_key", version=3)
'hello world!'
```

### キャッシュキーの変換

前の2つのセクションで説明したように、ユーザから提供されたキャッシュ・キーはそのまま使用されるわけではありません。このキーは、キャッシュ・プレフィックスおよびキーバージョンと組み合わされて最終的なキャッシュ・キーとなります。デフォルトでは、3 つの部分はコロンで結合されて最終的な文字列となります:

```
def make_key(key, key_prefix, version):
    return "%s:%s:%s" % (key_prefix, version, key)
```

各部分をさまざまな方法で組み合わせたり、最終的なキーに他の処理を施したりしたい場合は（例えば、キーの部品のハッシュダイジェストを取るなど）、独自のキー関数を作成できます。

[`KEY_FUNCTION`](/ja/5.1/ref/settings/#std-setting-CACHES-KEY_FUNCTION) キャッシュ設定では、上記の `make_key()` のプロトタイプにマッチする関数へのドット区切りパスを指定します。指定された場合、デフォルトのキー結合関数の代わりにこのカスタムキー関数が使用されます。

### キャッシュキーの警告

最も一般的に使用されているキャッシュバックエンドである Memcached は、 250 文字より長いキャッシュキーや、空白文字や制御文字を含むキャッシュキーを許可しておらず、そのようなキーを使用すると例外が発生します。キャッシュ移植可能なコードを推奨し、不快な驚きを最小化するために、他の組み込みキャッシュバックエンドは、 memcached でエラーを引き起こすようなキーが使用された場合、警告 (`django.core.cache.backends.base.CacheKeyWarning`) を出します。

より広い範囲のキーを使用できるバックエンド (カスタムバックエンド、または非emcachedの組み込みバックエンド) を使用していて、警告を出さずにより広い範囲のキーを使用したい場合は、 [`INSTALLED_APPS`](/ja/5.1/ref/settings/#std-setting-INSTALLED_APPS) の `management` モジュールにあるこのコードで `CacheKeyWarning` を無効にできます:

```
import warnings

from django.core.cache import CacheKeyWarning

warnings.simplefilter("ignore", CacheKeyWarning)
```

組み込みのバックエンドに対してカスタムキーバリデーションのロジックを提供したい場合は、そのバックエンドをサブクラス化して `validate_key` メソッドだけをオーバーライドし、 [using a custom cache backend](#id9) の説明に従ってください。たとえば、 `locmem` バックエンドに対してこの処理を行うには、次のコードをモジュールに記述します:

```
from django.core.cache.backends.locmem import LocMemCache

class CustomLocMemCache(LocMemCache):
    def validate_key(self, key):
        """Custom validation, raising exceptions or warnings as needed."""
        ...
```

...そして、このクラスへのドット区切りパスを [`CACHES`](/ja/5.1/ref/settings/#std-setting-CACHES) 設定の [`BACKEND`](/ja/5.1/ref/settings/#std-setting-CACHES-BACKEND) 部分で使用します。

## 非同期サポート

Django は非同期キャッシュバックエンドのサポートを開発中ですが、非同期キャッシュはまだサポートしていません。将来のリリースで対応する予定です。

`django.core.cache.backends.base.BaseCache` には [全ての基本メソッド](#cache-basic-interface) の非同期バージョンがあります。慣習として、すべてのメソッドの非同期バージョンのプレフィックスは `a` です。デフォルトでは、両方の引数は同じです:

```pycon
>>> await cache.aset("num", 1)
>>> await cache.ahas_key("num")
True
```

## ダウンストリームキャッシュ

これまで、このドキュメントは自分自身が *持つ* データに焦点を当ててきました。しかし、ウェブ開発では別の種類のキャッシュも関係があります。それは、「ダウンストリーム」のキャッシュによって実行されるキャッシングです。ユーザーのために、リクエストがウェブサイトに到達する前にもページをキャッシュするシステムが存在します。

ダウンストリーム キャッシュの例をいくつか挙げます。

- HTTPを使用する場合、あなたの ISP (Internet Service Provider) は特定のページをキャッシュすることがあります。そのため、もしあなたが `http://example.com/` からページをリクエストした場合、あなたのISPはexample.comに直接アクセスすることなく、あなたにそのページを送信します。example.comの管理者はこのようなキャッシュを知りません。ISPはexample.comとあなたのウェブブラウザの間に位置し、透過的にすべてのキャッシュを処理します。このようなキャッシュは、中間者攻撃（man-in-the-middle attack）となるため、HTTPSでは不可能です。
- あなたの Django ウェブサイトは、Squid Web Proxy Cache (<http://www.squid-cache.org/>) のような *プロキシキャッシュ* の背後にあるかもしれません。この場合、各リクエストはまずプロキシによって処理され、必要なときだけアプリケーションに渡されます。
- ウェブブラウザもページをキャッシュします。ウェブページが適切なヘッダーを送信すると、ブラウザはそのページへのその後のリクエストに、変更されたかどうかを確認するためにウェブページに再度問い合わせることなく、ローカルにキャッシュされたコピーを使用します。

ダウンストリーム・キャッシュは効率性を高めてくれますが、危険性もあります。 多くのウェブページのコンテンツは、認証や他の変数のホストに基づいて異なっており、純粋にURLに基づいてやみくもにページを保存するキャッシュシステムは、それらのページにあとから訪問する人に不正確なデータや機密データを公開する可能性があります。

たとえば、ウェブメールシステムを運営している場合、「受信トレイ」ページの内容は、どのユーザーがログインしているかによって異なります。もしISPがやみくもにあなたのサイトをキャッシュしていたら、そのISP経由で最初にログインしたユーザーは、そのユーザー固有の受信トレイページを、それ以降のサイト訪問者のためにキャッシュすることになります。 それはクールではありません。

幸い、HTTP はこの問題の解決方法を提供しています。さまざまな HTTP ヘッダを使用することで、指定した変数に応じてキャッシュ コンテンツを変えるようにダウンストリーム キャッシュに支持したり、特定のページをキャッシュしないようにキャッシュメカニズムに伝えることができます。以下のセクションでは、こうしたヘッダの一部を見ていきます。

## `Vary` ヘッダーを使う

`Vary` ヘッダは、キャッシュメカニズムがキャッシュキーを作る際に、どのリクエストヘッダを考慮するべきかを定義します。たとえば、ウェブサイトのコンテンツがユーザーの言語設定に依存する場合、ページは「言語によって異なる (vary)」と言うことができます。

デフォルトでは、Django のキャッシュシステムは、リクエストされた完全修飾 URL (たとえば `"https://www.example.com/stories/2005/?order_by=author"`) を使ってキャッシュキーを作成します。つまり、クッキーや 言語設定などのユーザエージェントの違いに関係なく、その URL へのリクエストはすべて同じキャッシュバージョンを使うことになります。しかし、もしこのページがリクエストヘッダの違い、例えばクッキーや言語、ユーザーエージェントの違いによって異なるコンテンツを生成するのであれば、 `Vary` ヘッダを使ってキャッシュ機構にページの出力がそれらに依存していることを伝える必要があります。

これを Django で行うには、便利な [`django.views.decorators.vary.vary_on_headers()`](/ja/5.1/topics/http/decorators/#django.views.decorators.vary.vary_on_headers) ビューデコレータを次のように使います:

```
from django.views.decorators.vary import vary_on_headers

@vary_on_headers("User-Agent")
def my_view(request): ...
```

この場合、(Django 自身のキャッシュミドルウェアのような) キャッシュ機構は、それぞれのユニークなユーザエージェントに対して、別バージョンのページをキャッシュします。

`vary_on_headers` デコレータを使用する利点は、手動で `Vary` ヘッダーを設定する (`response.headers['Vary'] = 'user-agent'` のように使用する) のではなく、デコレータが `Vary` ヘッダーに *追加* をする点にあります（これは既に存在するかもしれません）。それにより、最初から設定され、既にそこにあったものを上書きすることを避けることができます。

複数のヘッダを `vary_on_headers()` に渡すこともできます:

```
@vary_on_headers("User-Agent", "Cookie")
def my_view(request): ...
```

これは、下流のキャッシュに対して *両方* の vary に応じるように指示します。これは、user-agent と cookie の各組み合わせがそれぞれ独自のキャッシュ値を持つことを意味します。例えば、user-agent が `Mozilla` で cookie の値が `foo=bar` のリクエストは、user-agent が `Mozilla` で cookie の値が `foo=ham` のリクエストとは異なるものとみなされます。

クッキーで変化することはとても一般的なので、 [`django.views.decorators.vary.vary_on_cookie()`](/ja/5.1/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie) デコレータがあります。これら2つのビューは等価です:

```
@vary_on_cookie
def my_view(request): ...

@vary_on_headers("Cookie")
def my_view(request): ...
```

`vary_on_headers` に渡すヘッダは大文字小文字を区別しません。 `"User-Agent"` は `"user-agent"` と同じ意味です。

[`django.utils.cache.patch_vary_headers()`](/ja/5.1/ref/utils/#django.utils.cache.patch_vary_headers) というヘルパー関数を直接使うこともできます。この関数は `Vary ヘッダ` を設定、または追加します。たとえば次のようにします:

```
from django.shortcuts import render
from django.utils.cache import patch_vary_headers

def my_view(request):
    ...
    response = render(request, "template_name", context)
    patch_vary_headers(response, ["Cookie"])
    return response
```

`patch_vary_headers` は [`HttpResponse`](/ja/5.1/ref/request-response/#django.http.HttpResponse) インスタンスを第 1 引数に、大文字小文字を区別しないヘッダ名のリスト/タプルを第 2 引数にとります。

Vary ヘッダについての詳細は [**公式な Vary の仕様**](https://datatracker.ietf.org/doc/html/rfc9110.html#section-12.5.5) を参照してください。

## キャッシュの制御: 他のヘッダを使用する

キャッシュに関するその他の問題点としては、データのプライバシーや、キャッシュの階層構造のどこにデータを保存すべきかという問題があります。

ユーザーは通常2種類のキャッシュに直面します。自分のブラウザのキャッシュ（プライベートキャッシュ）とプロバイダのキャッシュ（パブリックキャッシュ）です。パブリックキャッシュは、複数のユーザーによって使用され、他の誰かによって制御されます。これは、機密データに関する問題を引き起こします。例えば、銀行の口座番号がパブリックキャッシュに保存されることは避けたいものです。そのため、ウェブアプリケーションには、どのデータがプライベートで、どのデータがパブリックであるかをキャッシュに伝える方法が必要です。

解決策は、ページのキャッシュを "private" にすることです。これを Django で行うには、 [`cache_control()`](/ja/5.1/topics/http/decorators/#django.views.decorators.cache.cache_control) ビューデコレータを使います。例:

```
from django.views.decorators.cache import cache_control

@cache_control(private=True)
def my_view(request): ...
```

このデコレータは、適切な HTTP ヘッダーを背後で送信します。

キャッシュ制御の設定 "private" と "public" は互いに排他的であることに注意しましょう。デコレータは、"private" が設定されているときは "public" ディレクティブを削除します (逆も同様です)。2つのディレクティブの使用例は、プライベートとパブリックのエントリを提供するブログサイトです。公開エントリは共有キャッシュにキャッシュされます。以下のコードでは [`patch_cache_control()`](/ja/5.1/ref/utils/#django.utils.cache.patch_cache_control) を使っています。これはキャッシュコントロールヘッダを手動で変更する方法です (内部的には [`cache_control()`](/ja/5.1/topics/http/decorators/#django.views.decorators.cache.cache_control) デコレータから呼び出されます):

```
from django.views.decorators.cache import patch_cache_control
from django.views.decorators.vary import vary_on_cookie

@vary_on_cookie
def list_blog_entries_view(request):
    if request.user.is_anonymous:
        response = render_only_public_entries()
        patch_cache_control(response, public=True)
    else:
        response = render_private_and_public_entries(request.user)
        patch_cache_control(response, private=True)

    return response
```

ダウンストリームのキャッシュは他の方法でも制御できます (HTTP キャッシュの詳細については [**RFC 9111**](https://datatracker.ietf.org/doc/html/rfc9111.html) を参照してください)。たとえば、 Django のサーバーサイドキャッシュフレームワークを使わない場合でも、 [**max-age**](https://datatracker.ietf.org/doc/html/rfc9111.html#section-5.2.2.1) ディレクティブを使って、ビューを一定時間キャッシュするようにクライアントに指示できます:

```
from django.views.decorators.cache import cache_control

@cache_control(max_age=3600)
def my_view(request): ...
```

(キャッシュミドルウェアを使用 *する* 場合、 [`CACHE_MIDDLEWARE_SECONDS`](/ja/5.1/ref/settings/#std-setting-CACHE_MIDDLEWARE_SECONDS) 設定の値で `max-age` が既に設定されています。その場合、 [`cache_control()`](/ja/5.1/topics/http/decorators/#django.views.decorators.cache.cache_control) デコレータで指定した `max_age` が優先され、ヘッダ値は正しくマージされます)。

有効な `Cache-Control` レスポンスディレクティブはすべて `cache_control()` で有効です。以下はその例です:

- `no_transform=True`
- `must_revalidate=True`
- `stale_while_revalidate=num_seconds`
- `no_cache=True`

既知のディレクティブの全リストは [IANA registry](https://www.iana.org/assignments/http-cache-directives/http-cache-directives.xhtml) にあります (すべてのディレクティブがレスポンスに適用されるわけではないことに注意してください)。

ヘッダーを使用してキャッシュを完全に無効にしたい場合は、 [`never_cache()`](/ja/5.1/topics/http/decorators/#django.views.decorators.cache.never_cache) が使えます。これはビューのデコレータであり、レスポンスがブラウザーや他のキャッシュによってキャッシュされないようにするヘッダーを追加します。例:

```
from django.views.decorators.cache import never_cache

@never_cache
def myview(request): ...
```

## `MIDDLEWARE` の順序

キャッシュミドルウェアを使用する場合、下記の2つを [`MIDDLEWARE`](/ja/5.1/ref/settings/#std-setting-MIDDLEWARE) 設定の適切な場所に配置することが重要です。キャッシュミドルウェアはどのヘッダによってキャッシュストレージを変化させるかを知る必要があるからです。ミドルウェアは常に `Vary` レスポンスヘッダに何かを追加します。

`UpdateCacheMiddleware` はレスポンスフェーズの間に実行され、ミドルウェアは逆順に実行されるため、リストの先頭にある項目はレスポンスフェーズの間、 *最後に* 実行されます。したがって、 `UpdateCacheMiddleware` が `Vary` ヘッダに何かを追加する可能性のある他のミドルウェアの *前に* 配置されていることを確認する必要があります。以下のミドルウェアモジュールは `Vary` ヘッダに何らかのものを追加します:

- `SessionMiddleware` は `Cookie` を追加します
- `GZipMiddleware` は `Accept-Encoding` を追加します
- `LocaleMiddleware` は `Accept-Language` を追加します

一方、`FetchFromCacheMiddleware` はリクエストフェーズで実行され、このフェーズではミドルウェアが先頭から最後にかけて適用されるため、リストの上部にあるアイテムはリクエストフェーズの *最初* に実行されます。 `FetchFromCacheMiddleware` もまた、他のミドルウェアが `Vary` ヘッダーを更新した後に実行する必要があるので、 `FetchFromCacheMiddleware` は `Vary` ヘッダーを更新するようなアイテムの *後* になければなりません。
