イベントのDB登録機能の実装
ビューの修正
イベントを登録するための処理を追加します。
リクエストのバリデーションと、DBへの登録処理を追加しました。
詳しくは、ソース中のコメントをご確認ください。
import json
from .models import Event
from .forms import EventForm
from django.http import Http404
import time
from django.template import loader
from django.http import HttpResponse
...
def add_event(request):
"""
イベント登録
"""
if request.method == "GET":
# GETは対応しない
raise Http404()
# JSONの解析
datas = json.loads(request.body)
# バリデーション
eventForm = EventForm(datas)
if eventForm.is_valid() == False:
# バリデーションエラー
raise Http404()
# リクエストの取得
start_date = datas["start_date"]
end_date = datas["end_date"]
event_name = datas["event_name"]
# 日付に変換。JavaScriptのタイムスタンプはミリ秒なので秒に変換
formatted_start_date = time.strftime(
"%Y-%m-%d", time.localtime(start_date / 1000))
formatted_end_date = time.strftime(
"%Y-%m-%d", time.localtime(end_date / 1000))
# 登録処理
event = Event(
event_name=str(event_name),
start_date=formatted_start_date,
end_date=formatted_end_date,
)
event.save()
# 空を返却
return HttpResponse("")
フォームクラスを作成します。
バリデーションルールを定義しています。
from django import forms
class EventForm(forms.Form):
start_date = forms.IntegerField(required=True)
end_date = forms.IntegerField(required=True)
event_name = forms.CharField(required=True, max_length=32)
登録処理のURLを追加します。
from django.urls import path
from . import views
app_name = "cal"
urlpatterns = [
path("", views.index, name="index"),
path("add/", views.add_event, name="add_event"),
]
JavaScriptの修正
非同期通信を行うためのaxiosを追加します。
index.htmlにCDNを使用して、axiosを追加します。
scheduleCalendar/index.html
<html>
<head>
<meta charset='utf-8' />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.2/main.min.css">
</head>
<body>
<div id='calendar'></div>
{% load static %}
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.2/main.min.js"></script>
<script src="{% static 'scheduleCalendar/app.js' %}"></script>
</body>
</html>
それではイベントを追加する処理に登録処理の呼び出しを実装してみましょう。
修正箇所だけ抜粋したコードです。
select: function (info) {
//alert("selected " + info.startStr + " to " + info.endStr);
// 入力ダイアログ
const eventName = prompt("イベントを入力してください");
if (eventName) {
// 登録処理の呼び出し
axios
.post("/sc/add/", {
start_date: info.start.valueOf(),
end_date: info.end.valueOf(),
event_name: eventName,
})
.then(() => {
// イベントの追加
calendar.addEvent({
title: eventName,
start: info.start,
end: info.end,
allDay: true,
});
})
.catch(() => {
// バリデーションエラーなど
alert("登録に失敗しました");
});
}
},
CSRFの対応を追記します。
JavaScriptの先頭に追記します。
// CSRF対策
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"
axios.defaults.xsrfCookieName = "csrftoken"
..
カレンダーの画面を表示した際に、CSRFのトークンを発行するようにします。
これがないと、CSRFの403エラーになります。
from django.template import loader
from django.http import HttpResponse
from django.middleware.csrf import get_token
# Create your views here.
def index(request):
"""
カレンダー画面
"""
# CSRFのトークンを発行する
get_token(request)
template = loader.get_template("scheduleCalendar/index.html")
return HttpResponse(template.render())
これで登録処理の流れができました。実際に試してみましょう。
以下のURLにアクセスします。
http://localhost:8000/sc/
プロンプトに任意のイベント名を入力します。
データベースに正しく登録されました。
エラー処理も確認してみましょう。
イベント名は32文字の文字数制限をかけましたので、32文字以上のイベント名を登録してみます。
失敗アラートが表示され、カレンダー上にイベントは表示されませんし、当然DBにも登録されません。
イベントの表示
ビューの修正
イベントの登録が完了しました。
今度はカレンダーの表示時に、データベースに登録されているイベントを表示します。
イベントを取得するための処理を追加します。
カレンダーが表示されている期間のみ、イベントを取得するようにします。
from django.http import JsonResponse
from .forms import CalendarForm
...
def get_events(request):
"""
イベントの取得
"""
if request.method == "GET":
# GETは対応しない
raise Http404()
# JSONの解析
datas = json.loads(request.body)
# バリデーション
calendarForm = CalendarForm(datas)
if calendarForm.is_valid() == False:
# バリデーションエラー
raise Http404()
# リクエストの取得
start_date = datas["start_date"]
end_date = datas["end_date"]
# 日付に変換。JavaScriptのタイムスタンプはミリ秒なので秒に変換
formatted_start_date = time.strftime(
"%Y-%m-%d", time.localtime(start_date / 1000))
formatted_end_date = time.strftime(
"%Y-%m-%d", time.localtime(end_date / 1000))
# FullCalendarの表示範囲のみ表示
events = Event.objects.filter(
start_date__lt=formatted_end_date, end_date__gt=formatted_start_date
)
# fullcalendarのため配列で返却
list = []
for event in events:
list.append(
{
"title": event.event_name,
"start": event.start_date,
"end": event.end_date,
}
)
return JsonResponse(list, safe=False)
フォームクラスを作成します。
バリデーションルールを定義しています。
from django import forms
..
class CalendarForm(forms.Form):
start_date = forms.IntegerField(required=True)
end_date = forms.IntegerField(required=True)
一覧取得処理のURLを追加します。
from django.urls import path
from . import views
app_name = "cal"
urlpatterns = [
path("", views.index, name="index"),
path("add/", views.add_event, name="add_event"),
path("list/", views.get_events, name="get_events"),
]
app.jsを開き、イベントを取得する処理を記述します。
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
...
events: function (info, successCallback, failureCallback) {
axios
.post("/sc/list/", {
start_date: info.start.valueOf(),
end_date: info.end.valueOf(),
})
.then((response) => {
calendar.removeAllEvents();
successCallback(response.data);
})
.catch(() => {
// バリデーションエラーなど
alert("登録に失敗しました");
});
},
});
calendar.render();
これでプログラムは完成です。
イベントを登録してみましょう。
DBにも格納されますので、ブラウザを閉じて再度カレンダーを表示してもイベントは表示されます。(永続化)
完成ソース
今回作成したプロジェクトのソース全容は、以下のリポジトリをご覧ください。
機密情報の管理
SECRET_KEYなどの機密情報を別ファイルで管理する方法は、以下の記事をご覧ください。
その他
外部サーバーへ公開
作成したアプリは公開して使ってもらいましょう!
Djangoアプリケーションを外部公開する方法をまとめました。
脆弱性対策
脆弱性を抱えたアプリケーションの場合、攻撃を受ける可能性があり大変危険です。
作成したアプリケーションは、脆弱性対策も意識しましょう。
GitHubと連携
GitHubと連携する方法を解説しました。
プロジェクトの管理はGitHubを活用しましょう。
GitHub Copilot
GitHub Copilotを導入し、AIにコーディングをサポートしてもらうこともできます。
さいごに
簡単なスケジュールを登録するWebアプリケーションを作成しました。
カレンダーを利用するケースはよくあると思いますが、活用してみましょう。
他にも私のブログで、Djangoについて解説している記事がありますのでご覧ください。
コメント