アラフォーから色々始めるリケジョの独り言

アラフォーになって色々始めてみました手探りでがんばります。

djangoでGoogleカレンダーに予定を登録するアプリを作りたい【2】

前回から時間があいてしまって(引っ越しとかで忙しく)、色々忘れてしまってたのだけど、また一歩ずつ。

 

前回はきっと認証がとりあえずできた、ってところで終わってた??

 

  • やりたいこと①予定の登録をできるようにする
  • やりたいこと②予定の一覧を出せるようにする
  • やりたいこと③予定の編集・削除をできるようにする
  • やりたいこと④予定の一覧を他の人のGoogleカレンダーに登録できるようにする
  • やりたいこと⑤ChatGPTと連携したい

みたいな感じで、とりあえずこの土日で①②ができるといいなという感じ。

 

【やりたいこと①予定の登録をできるようにする】

新しく作ったものは以下3つの関数。

ChatGPTに「djangoGoogleカレンダーに予定を登録するプログラムを作りたいです。setting.pyとviews.pyとurls.pyに記載することと、必要なHTMLを教えてください。」という何とも曖昧な聞き方からのスタート。

あとはググったんだけど、参考URLを忘れてしまった・・・

 

def create_event(request):

メインの関数。

認証してるかの確認。してなければauthorizeを呼ぶ。

POSTなら投げられてきたFormの情報をGoogleカレンダーに登録する。

 

def authorize(request):

Googleの認証ページにリダイレクトし、アプリケーションにアクセスを許可するための関数。(by chatGPT)

 

def oauth2callback(request):

これが何かいまだによくわかってない。setting.pyで

LOGIN_URL = '/oauth2callback/'

と入れてるので呼ばれてるもの。

ユーザーがGoogleの認証ページで承認した後にリダイレクトされるコールバック関数。(by chatGPT)

 

 

すんごい色々エラーが出て、それをひとつひとつChatGPTに聞きながら解決していくんだけど、一番時間がかかったのは

'str' object has no attribute 'keys'

これがもうずっと出て、認証してくれないって言う・・・

credential.jsonファイルがうまくセッションに入れられなくて・・・

文字列だとか辞書型だとかの言い回しがchatGPTの言うことがころころ変わって初心者の私は大混乱・・・

chatGPTへの問いかけの仕方が大事なんだなーと実感です。

 

最終的なview.pyはこちら。

from django.shortcuts import render,redirect
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import Flow,InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from django.conf import settings
from django.contrib import messages
from .forms import EventForm
from datetime import datetime
import pytz
import os
import json

credentials_path = os.path.join(settings.BASE_DIR, 'credentials.json')

def create_event(request):
    #認証の確認
    #最初に、セッションにcredentialsが含まれているかどうかをチェックします。これは、ユーザーが事前にGoogleカレンダーへのアクセスを許可したかどうかを確認します。
    #もしcredentialsがセッションに含まれていない場合、authorizeビューにリダイレクトします。これにより、ユーザーはGoogleにログインしてアプリケーションへのアクセスを許可できます。
    if 'credentials' not in request.session:
        return redirect('authorize')
   
    #認証情報の取得:
    #もしcredentialsがセッションに含まれている場合、それを使って認証情報を取得します。
    #from_authorized_user_infoメソッドは、セッションから認証情報を取得し、Credentialsオブジェクトを作成します。
    #Googleカレンダーサービスの作成:
    #認証情報が取得できたら、buildメソッドを使用してGoogleカレンダーサービスを作成します。
    #これにより、GoogleカレンダーAPIにアクセスするためのサービスオブジェクトが作成されます。
    credentials = Credentials.from_authorized_user_info(json.loads(request.session['credentials']))
    service = build('calendar', 'v3', credentials=credentials)

    #フォームの処理:
    #フォームがPOSTリクエストで送信された場合、入力されたデータを使用して新しい予定を作成します。
    #フォームが有効な場合、入力されたデータから予定の情報を取得し、Googleカレンダーに予定を追加します。
    #この際、service.events().insert()メソッドを使用してAPIリクエストを行います。
    #予定が作成された後、成功メッセージを表示し、再度予定を作成するためのフォームを表示します。
    if request.method == 'POST':
        form = EventForm(request.POST)
        if form.is_valid():
            #GoogleAPIに渡すには文字列にしないといけない
            start_date = form.cleaned_data['start_date'].strftime('%Y-%m-%d')
            end_date = form.cleaned_data['end_date'].strftime('%Y-%m-%d')
            print(form.cleaned_data['all_day'])
           
            if form.cleaned_data['all_day']:
                start_datetime = start_date
                end_datetime = end_date
               
                event = {
                    'summary': form.cleaned_data['summary'],
                    'location': form.cleaned_data['location'],
                    'description': form.cleaned_data['description'],
                    'start': {
                        'date': start_datetime,
                        'timeZone': 'Asia/Tokyo',
                    },
                    'end': {
                        'date': end_datetime,
                        'timeZone': 'Asia/Tokyo',
                    },
                }
            else:
                start_time = form.cleaned_data['start_time'].strftime('T%H:%M:%S')
                end_time = form.cleaned_data['end_time'].strftime('T%H:%M:%S')
 
                start_datetime = start_date+start_time
                end_datetime = end_date+end_time
               
                event = {
                    'summary': form.cleaned_data['summary'],
                    'location': form.cleaned_data['location'],
                    'description': form.cleaned_data['description'],
                    'start': {
                        'dateTime': start_datetime,
                        'timeZone': 'Asia/Tokyo',
                    },
                    'end': {
                        'dateTime': end_datetime,
                        'timeZone': 'Asia/Tokyo',
                    },
                }
            try:
                # GoogleカレンダーAPIを呼び出すコード
                service.events().insert(calendarId='primary', body=event).execute()
                messages.success(request, '登録成功!')
                return render(request, 'create_event.html', {'form': form})
                #return redirect('create_event')
            except Exception as e:
                # エラーが発生した場合の処理
                print(f"GoogleカレンダーAPIからエラーが返されました: {e}")
                #print(f"エラーレスポンスの詳細: {e.response}")        
                messages.error(request, 'フォーム形式がおかしい失敗・・・')
                return render(request, 'create_event.html', {'form': form})

        else:
            messages.error(request, '登録失敗・・・')
            return render(request, 'create_event.html', {'form': form})
    else:
        #フォームの表示:
        #GETリクエストの場合、新しい予定を作成するためのフォームを表示します。
        #フォームはEventFormクラスからインスタンス化されます。
        form = EventForm()
    #テンプレートへのデータの渡し方:
    #render関数を使用して、event_create.htmlテンプレートにフォームを渡します。
    #テンプレート内でフォームを使用して、ユーザーが予定の詳細を入力できるようになります。
    return render(request, 'create_event.html', {'form': form})


def authorize(request):
    flow = Flow.from_client_secrets_file(
        credentials_path,
        redirect_uri=settings.GOOGLE_CALENDAR_REDIRECT_URI
        )
    authorization_url, state = flow.authorization_url(access_type='offline', include_granted_scopes='true')
    request.session['state'] = state
    return redirect(authorization_url)


def oauth2callback(request):
    state = request.session.get('state', None)
    flow = Flow.from_client_secrets_file(
        credentials_path,
        state=state,
        redirect_uri=settings.GOOGLE_CALENDAR_REDIRECT_URI)
    flow.fetch_token(authorization_response=request.build_absolute_uri())
   
    request.session['credentials'] = flow.credentials.to_json()    
    return redirect('create_event')



 

で、見た目はともかくとして

予定登録画面

こんなのができました。

 

雑すぎる備忘録・・・

備忘録つけながらだと余計に時間がかかるから並行してできなくて💦

いやほんと時間が溶ける~~~~~本日も気づいたら朝6時になってしまいました。

寝なきゃ~~~