在 Django 中使用 google api

using google api eith django

我正在尝试将 py 项目的事件连接到 google 日历。我的应用程序没有使用 google 登录,因为它仅供一小部分人使用。我一直在寻找如何完成它的时间,但它不起作用。感谢任何帮助。

models.py

class AgendaClient(models.Model): # used to store info(same as enviroment variables)
    name = models.CharField(max_length=30, null=True, blank=True, unique=True)
    json = models.TextField(blank=True, null=True)

class Event(models.Model):
    summary = models.CharField(max_length=50, choices=EVENT_CHOICES)
    description = models.CharField(max_length=50, null=True, blank=True)
    start_date = models.DateField()
    google_link = models.CharField(max_length=150, null=True, blank=True)

signals.py

import datetime
import json

from django.db.models.signals import post_delete, post_save
from google.auth.transport.requests import Request
from google.cloud import storage
from google.oauth2 import service_account
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from users.models import Lid

from .models import AgendaClient, Event, NIEvent

# If modifying these scopes, delete the file token.json.
try:
    SCOPES = (AgendaClient.objects.get(name='SCOPES').json).strip("][").split(', ')
except: pass
def get_service(refresh = False):
    '''this functions gets and builds the service using the token and the client_secret'''
    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if len(AgendaClient.objects.filter(name='token'))==1:
            creds = Credentials.from_authorized_user_info(json.loads(AgendaClient.objects.get(name='token').json), SCOPES)
    else:
        # pprint(json.loads(AgendaClient.objects.get(name='service_account').json))
        creds = service_account.Credentials.from_service_account_info(json.loads(AgendaClient.objects.get(name='service_account').json), scopes=SCOPES)

    # Explicitly use service account credentials by specifying the private key
    # file.
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            # pprint(json.loads(AgendaClient.objects.get(name='client_secret').json))
            flow = InstalledAppFlow.from_client_config(
                    json.loads(AgendaClient.objects.get(name='client_secret').json), SCOPES)
            creds = flow.run_local_server(port=0)
            # creds = service_account.Credentials.from_service_account_info(json.loads(AgendaClient.objects.get(name='service_account').json), scopes=SCOPES)

    # Save the credentials for the next run
    AgendaClient.objects.update_or_create(name='token', defaults = {'json':creds.to_json()})
    if not refresh:
        service = build('calendar', 'v3', credentials=creds)
        return service
    
def handle_event(sender,created, instance=None,  **kwargs):
    """this function creates the events in the google agenda and updates them if changed in the website
    """
    service = get_service()
    evs = instance
    event ={
    'summary': evs.description,
    'location': evs.location or "",
    'description': (evs.description+' '+ evs.summary),
    'start': {
        'dateTime': datetime.datetime.combine(evs.start_date,evs.start_time).isoformat(),
        'timeZone': 'Europe/Amsterdam',
    },
    'end': {
        'dateTime':datetime.datetime.combine(evs.end_date,evs.end_time).isoformat() ,
        'timeZone': 'Europe/Amsterdam',
    },
    'recurrence': [],'reminders': {}}

    if created or not instance.google_link:
        try:
            event = service.events().insert(calendarId=AgendaClient.objects.get(name='calendarId').json, body=event).execute()
            instance.google_link = event['id']
            instance.save()
        except HttpError as error:
            print('An error occurred: %s' % error)
            pass
    else:  
        try:
            # print(type(AgendaClient.objects.get(name='calendarId').json))
            event = service.events().update(calendarId=AgendaClient.objects.get(name='calendarId').json, body=event, eventId = instance.google_link).execute()
        except HttpError as error:
            print('An error occurred: %s' % error)
            pass

post_save.connect(handle_event, sender=Event)

理想情况下,我会使用服务帐户,这样用户就不必登录 google。也许有人知道比这更好的解决方案,但本质上,网站应该能够将事件添加到用户可以关注的日历中,但不能将事件添加到每个用户的日历中。

问题的主要原因是您似乎试图在同一代码中混合使用服务帐户授权和已安装的应用程序授权。

就代码的服务帐户部分而言,请记住具有 Google 日历和 google 工作区帐户的服务帐户。确保您已正确配置对域中您希望服务帐户委托的用户的委派。

from google.oauth2 import service_account

SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'

credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)
delegated_credentials = credentials.with_subject('user@example.org')

在查看了所有地方后,我找到了答案。我将其发布在 下,因为那是我获得所需大部分信息的地方

感谢帮助