概要
DjangoをSqliteを使わずにDynamoDBだけで実装したいときに役に立ちそうなことを記事にしました。
今回はDjangoからDynamORMを使ってDynamoDBを操作したり、session機能をDynamoDBで実装したりします。
Djangoの設定
まず、以下のライブラリをインストールします。
pip install dynamorm
pip install marshmallow
pip install django-dynamodb-sessions
今回はセッション情報もDynamoDBに保存します。AWS_ACCESS_KEY_ID
などはAWS
のIAM
で取得してください。
# セッションを使うための設定
INSTALLED_APPS = [
'django.contrib.sessions',
]
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
]
SESSION_ENGINE = 'dynamodb_sessions.backends.dynamodb'
# セッションの有効期間などを設定
SESSION_COOKIE_AGE = 3600
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_SAVE_EVERY_REQUEST = True
# AWSのアクセスIDとシークレットIDを追記
DYNAMODB_SESSIONS_AWS_ACCESS_KEY_ID = 'YOUR_AWS_ACCESS_KEY_ID'
DYNAMODB_SESSIONS_AWS_SECRET_ACCESS_KEY = 'YOUR_AWS_SECRET_ACCESS_KEY_ID'
DYNAMODB_SESSIONS_AWS_REGION_NAME = 'ap-northeast-1'
# DynamORMの設定
AWS_ACCESS_KEY_ID = 'YOUR_AWS_ACCESS_KEY_ID'
AWS_SECRET_ACCESS_KEY = 'YOUR_AWS_SECRET_ACCESS_KEY_ID'
DynamoDBの操作
まずmodels.pyで以下のモジュールをインポートしてください。
今回はDynamORM
を使用します。
from dynamorm import DynaModel
from marshmallow import fields
モデルは以下のようにします。
nameに操作したいDynamoDBのテーブル名を、hash_keyにユニークなIDを入れます。
class SampleTable(DynaModel):
class Table:
name = "SmapleTable"
hash_key = 'SampleId'
read = 25
write = 5
class Schema:
SampleId = fields.String(required=True)
name = fields.String()
age = fields.Number()
ここまででDynamoDBを使う準備ができました。これからは実際に動かしていきます。
操作
では実際にDynamoDBにデータを作成してみます。まず,DyanmoDBのページでSampleTable
を作成します。
次にviews.pyに以下のコードを入れて実行してみます。
from .models import SampleTable
def index(request):
s = SampleTable(SampleId="sample1", name="neko", age="21")
s.save()
return HttpResponse("Hello, world. You're at the index.")
そしてindexを実行するとDynamoDBにデータが作成されているのが確認できます。
DynamORMで操作できる一部の例を紹介します。
from .models import SampleModel
# データ作成
s = SampleModel(id="sample1", name="neko", age="21")
s.save()
# データ取得
s = SampleModel.get(id='sample1')
# データを更新
# partial=Trueを付けない場合他の属性も更新される
s = SampleModel.get(id='sample1')
s.name = "inu"
s.save(partial=True)
# 以下の記述でも可能
s.update(name="inu")
DynamORMについて詳しく知りたい方は以下のサイトから
Session
ここまでDynamORMでのデータベース操作を行ってきました。
ここからはsessionの機能をdynamodbで実装していきます。
まず、dynamoDBでセッション用のテーブルsessions
を作成します。プライマリキーはSessionId
に設定しました。
Sessionの保存
request.session.save()
がなくても保存されますがこちらのほうがより確実です。
request.session['Id'] = SampleId
request.session.save()
これを実行すると以下のようにSessionId
とdata
が出てくると思います。
SessionIdにはsession_keyの値が入り、dataにはSampleIdの情報が入っています。
session_keyの取得
session_key = request.session.session_key
データの取得
Id = request.session.get('Id')
sessionを削除
request.session.flush()
sessionに関する他の操作は以下のサイトが役立ちます。
sessionの詳細設定
settings.pyにsessionの詳細設定を追記して反映します。
参考:
設定 | 説明 | デフォルト値 |
---|---|---|
DYNAMODB_SESSIONS_TABLE_NAME | DynamoDBのテーブル名。 | sessions |
DYNAMODB_SESSIONS_TABLE_HASH_ATTRIB_NAME | sessionテーブルの属性名。 | session_key |
SESSION_COOKIE_AGE | sessionの有効期限を設定 | 2週間 |
SESSION_EXPIRE_AT_BROWSER_CLOSE | ブラウザを閉じたときにsessionを消す | False |
SESSION_SAVE_EVERY_REQUEST | requestが来るたびにsessionの有効期限をリセット | False |
使わなくなったSessionを削除
sessionはログアウト時に実行されるrequest.session.flush()
によって削除されます。
また、setting.py
に記述した設定によって期限が過ぎた場合などにsessoin
は自動的に無効になります。しかし、ログアウトを実行せずにsessionが無効かされた場合はDynamoDB
には残り続けます。
自分でいらなくなったsession
をDynamoDB
から消してもいいですが、DynamoDB
のTTL
という機能を使えば自動的に削除できます。
TTL
TTLというのはDynamoDBのデータを自動的に削除してくれる機能です。DynamoDb
の概要
から設定できます。
今回は後に示すサンプルコードでsessions
にExpireTime
という属性を追加しました。
このExpireTime
をTTL
に監視してもらい、期限を過ぎたら削除してもらいます。
注意点としてはTTL
が監視してくれる時間はUNIX時間でないといけません。
サンプル
実際に動くサンプルコードを用意しました。
このサンプルコードではsessions
テーブルにExpiretime
を追加してTTL
を行えるようにしています。
また,htmlを作成していないため動かす際はURLから直接実行してください。
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('login', views.login, name='login'),
path('logout', views.logout, name='logout'),
]
models.py
from django.db import models
from dynamorm import DynaModel
from marshmallow import fields
class Session(DynaModel):
class Table:
name = "sessions" #DyanmoDBのSessionを保存するテーブル名
hash_key = 'SessionId'#プライマルキー
read = 25
write = 5
class Schema:
SessionId = fields.String(required=True)
ExpireTime = fields.Decimal()
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Session
from datetime import datetime
from decimal import Decimal
from dateutil.relativedelta import relativedelta
# User name=keita id=1 がいると仮定すると
def index(request):
return HttpResponse("Hello, world. You're at the index.")
def login(request):
if request.session.session_key:
Id = request.session.get('Id')
return HttpResponse(f"You're already logined ID={Id}")
else:
#sessoinを発行
request.session['Id'] = 1
request.session.save()
#sessionにExpireTime(1か月)を追加
date_time = Decimal(int((datetime.now()+relativedelta(months=1)).timestamp()))
s = Session.get(SessionId=request.session.session_key)
s.update(ExpireTime=date_time)
s.save(partial=True)
return HttpResponse("You're Logging")
def logout(request):
if request.session.session_key:
request.session.flush()
return HttpResponse("You're Logout")
else:
return HttpResponse("You're not Logging")
python manage.py runserver
を実行すると、Hello, world. You're at the index.というページが出てきます。
ログイン
今回はId=1のユーザーがログインすることを仮定して行います。 今回はパスワードなどはなしで実装しています。
session
にExpireTime
という属性を追加していますが、これは後でsessionを自動的に削除するために必要なものです。
また、request.session.keys()
で自分のsessionが存在するか確認できます。返り値はdict_keys(['Id'])
のようになっていて、sessionに何が入っているかを確認できます。
def login(request):
if request.session.keys(): #ログインしていたら(sessionキーが存在していたら)
Id = request.session.get('Id')
return HttpResponse(f"You're already logined ID={Id}")
else:#ログインしていなかったら
#sessoinを発行
request.session['Id'] = 1
request.session.save()
#sessionにExpireTime(1か月)を追加
date_time = Decimal(int((datetime.now()+relativedelta(months=1)).timestamp()))
s = Session.get(SessionId=request.session.session_key)
s.update(ExpireTime=date_time)
s.save(partial=True)
return HttpResponse("You're Logging")
URLをhttp://127.0.0.1:8000/login
としてクリックするとYou're Logging
と表示されるはずです。この時DynamoDbのsessionsテーブルを確認すると以下のようになっているはずです。
もう一度URLをhttp://127.0.0.1:8000/login
を訪問すると、sessionが存在していればYou're already logined ID=1
と出てきます。こうなっていれば、ログイン成功です!
ログアウト
def logout(request):
#ログインしていればsessionを削除
if request.session.keys():
request.session.flush()
return HttpResponse("You're Logout")
else:
return HttpResponse("You're not Logging")
では次はhttp://127.0.0.1:8000/logout
を訪問してみます。するとYou're Logout
と出てくると思います。sessionが削除されてログアウトされている状態です。下の画像のようにDynamoDBのsessioinからデータが消えているはずです。
まとめ
DjangoでDynamoDBを使いたいと思ったときに役に立ちそうなことを書きました。
sessionを使ってログイン機能等を作れると思うので参考になったらうれしいです
何か間違っているところがあったらコメントいただけるとありがたいです。