DjangoのCookieの取得・保存方法(COOKIES, set_cookie)
- 作成日: 2021-08-17
- 更新日: 2023-12-24
- カテゴリ: Django
Djangoのcookieの取得・保存方法
DjangoではCookie(クッキー)を扱うことが出来ます。
Cookieはクライアントサイドでも利用できる一時的なデータ保存領域のことで、これを使うとサイトに状態を持たせることが可能です。
Cookieにサイトのクリティカルなデータを保存するのは危険ですが、一時的な重要でないデータを保存するにはCookieはうってつけです。
この記事ではDjangoでCookieを取得・保存する方法について解説したいと思います。
具体的には↓を見ていきます。
- Cookieとは?
- DjangoでCookieを取得する
- DjangoでCookieを保存する
- クライアントサイド(JavaScript)でCookieを利用する
Cookieとは?
Cookie(クッキー)とはブラウザでWebサイトにアクセスした際に、ブラウザが作成するファイルのことを言います。
このファイルにはWebサイトが指定した情報などが保存されます。
ユーザーはこのファイルを利用することで、ステートレスなHTTPで状態を持った通信を行うことが出来ます。
たとえばECサイトのショッピング・カートの情報などです。カートの情報は別のページに移動した際にも保存されている必要がありますが、こういった状態を持ったロジックにはCookieやセッションなどが使われます。
Cookieはユーザーが自由に削除することが出来ます。そのため揮発的なデータと言えます。
また、Cookieはユーザーが自由に閲覧することが出来るため、Webサイトにとってクリティカルで重要なデータを保存するのには向いていません。
あくまで一時的で、重要でないデータを保存するのにCookieは使われます。
ショッピングカートで言えば、商品のIDなどがそうです。これらのIDは流出しても問題がないと見なされて、Cookieに保存されることがあります。
DjangoでCookieを取得する
DjangoでCookieを取得するには、request
からCOOKIES
を参照します。
このCOOKIES
は辞書風のオブジェクトで、get()
メソッドなどで値を取得することが出来ます。
たとえばcount
という名前のCookieの値を取得するには↓のようにします。
def home_view(request):
...
count = request.COOKIES.get('count', 0)
...
↑の場合、count
には0
かあるいは既存のcount
の値が入ります。
get()
メソッドは第1引数のキーの値を取得しますが、第2引数にはそのキーが存在しなかった場合のデフォルト値を指定することが出来ます。
なぜクライアントサイドで参照されるCookieがサーバーサイドで取得できるのか?
Cookieはブラウザに保存されるものですが、HTTP通信の時にCookieヘッダーというヘッダーにクッキーがセットされます。
このヘッダーはサーバーサイドで解析することが可能です。
そのためDjangoもこのヘッダーを解析して、COOKIES
に値を保存しているということになります。
ちなみにCOOKIES
はWSGIRequest
のプロパティです。
このWSGIRequest
はdjango/core/handlers/wsgi.py
から参照することが出来ます。
COOKIES
は@cached_property
でデコレートされたプロパティで、内部では環境からHTTP_COOKIE
という生のCookieを取り出し、それをparse_cookie()
という関数でパースしています。その結果がCOOKIES
の返す値です。
DjangoでCookieを保存する
DjangoでCookieを保存するにはレスポンスのメソッドset_cookie()
を使います。
def simple_view(request):
response = HttpResponse()
response.set_cookie('count', 1)
return response
↑の場合、レスポンスのCookieにはcount=1
がセットされます。
set_cookie()の構造
set_cookie()
は↓のような構造になっています。
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
domain=None, secure=False, httponly=False, samesite=None)
set_cookie()
は内部ではcookies
というクラスの属性にCookieを保存します。
このcookies
はSimpleCookie
というオブジェクトで、これはdjango/http/cookie.py
から参照することが出来ます。
expires
の値は以下の値である必要があります。
- 文字列(正しい日付のフォーマット)
- ナイーブ(
naive
)なdatetime.datetime
オブジェクト(UTC) - アウェア(
aware
)なdatetime.datetime
オブジェクト(いずれかのタイムゾーン) - (もし
datetime.datetime
であればmax_age
を計算します)
naive
とaware
については↓に詳しく書かれています。
Aware オブジェクトと Naive オブジェクト - datetime --- 基本的な日付型および時間型 — Python 3.9.4 ドキュメント
簡単に言うとnaive
はタイムゾーンなどの時間情報を持たないオブジェクトです。
いっぽうaware
はタイムゾーンや夏時間情報などを持ちます。
これらのオブジェクトは属性tzinfo
がNone
ならnaive
に、それ以外はaware
になります。
クライアントサイド(JavaScript)でCookieを利用する
サーバーサイドで設定したCookieをクライアントサイドで参照したい場合は↓のようなコードを書きます。
from django.http import HttpResponse
def home_view(request):
response = HttpResponse('''
<script>
let cookies = document.cookie.split(';')
for (const c of cookies) {
const kv = c.split('=')
if (kv[0].replace(/^\s+/g, '') === 'count') {
document.write(kv[1])
}
}
</script>
''')
count = request.COOKIES.get('count', 0)
count = int(count) + 1
response.set_cookie('count', count)
return response
↑のビューは、まず<script>
タグを含んだレスポンスを生成します。
その後にCOOKIES
を参照してcount
を取得します。
そしてcount
の値を1増やして、set_cookie
でレスポンスにCookieをセットします。
最後にそのレスポンスを返します。
<script>
タグ内ではdocument.cookie
の値を参照しています。
これは生のCookieなので目的の値を取り出すにはパースが必要です。
そのため↑のようにfor
文などを回してcount
の値を取り出すようにしています。
↑のビューを実行すると、画面にcount
の値が表示されます。
そしてブラウザを更新するたびに値が増えていきます。
おわりに
今回はDjangoのCookieを見てみました。
Cookieはよく使われるツールの1つですが、Djangoでは簡単に扱うことが可能です。
🦝 < クッキーが一枚、クッキーが二枚
🐭 < あれ? 一枚足りないな