はじめに
こんにちは、reimeiです。
先日Djangoで開発しているwebアプリケーションにてDBに保存しているスケージュールをiCalendarファイルに書き出して返す処理を実装しようとした際、つまづいたので共有しようと思います。
解決策
▼とりあえず、必要なライブラリをインストール
$ pip3 install ics
▼実装例
from ics import Calendar, Event
import arrow
import os
from django.http import HttpResponse
def download_icalendar_file(request):
calendar = Calendar()
event = Event()
event.name = "飲み会"
event.begin = arrow.get("2022-2-3 20:00:00", "YYYY-MM-DD HH:mm:ss") \
.replace(tzinfo='Asia/Tokyo')
event.end = arrow.get("2022-2-3 23:30:00", "YYYY-MM-DD HH:mm:ss") \
.replace(tzinfo="Asia/Tokyo")
calendar.events.add(event)
with open('calendar.ics', 'w') as f:
f.write(str(calendar))
with open('calendar.ics', 'rb') as f:
response = HttpResponse(f.read(), content_type="text/calendar")
response['Content-Disposition'] =\
'inline; filename=' + os.path.basename('schedule.ics')
os.remove('schedule.ics')
return response
解説
必要なライブラリをインポートしている。
from ics import Calendar, Event
import arrow
import os
from django.http import HttpResponse
カレンダーやイベント情報の設定を行っている。 `event = Event()` 以下を繰り返し実行すると複数のイベント情報を持つカレンダーを作成することができる。 時間は何もせずに設定すると世界標準の時間になってしまうので時差を計算するか以下のようにタイムゾーンを変更するなどの処理を行う必要があるので注意。
calendar = Calendar()
event = Event()
event.name = "飲み会"
event.begin = arrow.get("2022-2-3 20:00:00", "YYYY-MM-DD HH:mm:ss") \
.replace(tzinfo='Asia/Tokyo')
event.end = arrow.get("2022-2-3 23:30:00", "YYYY-MM-DD HH:mm:ss") \
.replace(tzinfo="Asia/Tokyo")
calendar.events.add(event)
calendar.icsという名前のファイルにカレンダー情報を書き込んでいる。
with open('calendar.ics', 'w') as f:
f.write(str(calendar))
カレンダーファイルをクライアントに返すためのレスポンスの設定を行っている。 また、作成したschedule.icsが残り続けると邪魔なので削除も行っている。 ▼メディアタイプには `text/calendar` という形式があるらしい(今回初めて知った)
with open('calendar.ics', 'rb') as f:
response = HttpResponse(f.read(), content_type="text/calendar")
response['Content-Disposition'] =\
'inline; filename=' + os.path.basename('schedule.ics')
os.remove('schedule.ics')
return response
あとはurls.pyでリンクを設定したり、そのリンクをtemplateに貼り付ければ完成!
最後に
今回DjangoでiCalendarファイルをダウンロードする機能を実装していた際、躓いたが日本語の記事が見つからなかったのでまとめてみました。
また、今回紹介した解決方法よりも良い方法をご存知の方は教えていただきたいです!
(特にレスポンスの設定をいじっているあたり)