DjangoでGoogle Calendarへアクセス①

こんなことがしたかった

  • CreateViewでDBにデータがInsertされたときに、Google Calendarにもイベントを登録したかった

厳密にはもう少し複雑ではあるのだが、Djangoで作った予定管理アプリのようなものに予定を追加したときに、Google Calendarにも同期したかったのである。

最終的には双方向で同期するようにしたいのではあるが、とりあえずはDjangoアプリ→Google Calendarの方。

こんな感じ

前提として、Google Cloud ConsoleからGoogle Calendar APIを有効化し、サービスアカウントを作成しておく。

かつ、そのサービスアカウントにGoogle Calendarの予定の変更権限を渡しておく。

また、pipで必要な以下のライブラリも入れておく。

github.com

github.com

プログラムは以下。※動かなかったらごめんなさい

  • Views.py
import requests
import json
import os.path
import httplib2

from django.conf import settings
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
from google.auth.transport.requests import Request

from app.forms import Form
from app.models import Model

class CreateView(CreateView):
    model = Model
    form_class = Form
    template_name = 'create.html'

def form_valid(self, form):
        obj = form.save(commit=False)

  # Google Calendarに追加する予定のデータを作成
        gcal_ctx={
                'summary':'タイトル',
                'start':{
                    'dateTime':予定の開始日時,
                    'timeZone':'UTC'
                },
                'end':{
                    'dateTime':予定の終了日時,
                    'timeZone':'UTC'
                },
            }
            # Google Calendarに予定データを渡してInsert、返り値のeventidを格納
            gcal_eventid = self.insertgcal(gcal_ctx)
            
            # Google CalendarのイベントIDを記録
            obj.gcal_eventid = gcal_eventid
            obj.save()

        return redirect('処理完了画面')

# Google CalendarにInsertする関数
def insertgcal(self, body):
        # 認証情報を作成
        credentials = ServiceAccountCredentials.from_json_keyfile_name(
            settings.GCAL_PRIVATE_KEY_PATH,
            scopes=settings.GCAL_SCOPES
        )
        http = credentials.authorize(httplib2.Http())
        service = build('calendar', 'v3', http=http)

        event = service.events().insert(calendarId=settings.GCAL_CALENDAR_ID, body=body).execute()
        # idを返してDBにidを入れる
        return event.get("id")
  • settings.py
〜前略〜
# GCAL
GCAL_PRIVATE_KEY_PATH = 'サービスアカウントのjson'
GCAL_SCOPES = ['https://www.googleapis.com/auth/calendar']
GCAL_CALENDAR_ID = 'Google CalendarのID'
  • その他 アプリケーションのルートに「サービスアカウントのjson」ファイルを配置しておくこと。

ようするに、InsertしたデータからGoogle Calendarのイベントを作り、認証をとおして、Google側が準備した「service.events().insert」を使ってカレンダー側にも反映させるのであった。

また、Google Calendar側のIDを取得しておき、Django側にも持たせておかないと、Google CalendarDjango側の取得のときに面倒なことになるので、そういった処理も入れている。

実装してみて

実装自体はそれほど難しくなかったのだが、Google APIの認証がちょっと厄介だった。

最初はブラウザでの認証が必要な別の方式でやっていたが、サーバに載せたときにサービスアカウント方式でないと詰まることがわかり急遽認証方式を変更したのが主なトラブル。

何に使うにしても汎用性は高そうな気もする。

参考文献

個人のGoogleカレンダーの予定をPythonで取得する | ヤマムギ

オフィスへの来訪申請をGoogleカレンダーと連携させて自動化してみたよ|Holidayおでかけラボ|note

【Python】Google Calendar APIを使ってGoogle Calendarの予定を取得・追加する | 無次元日記

Events  |  Calendar API  |  Google Developers