使用Google API EITH DJANGO

发布于 2025-01-31 12:10:06 字数 4639 浏览 5 评论 0原文

我正在尝试将事件与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。也许有人比这更好的解决方案知道,但是本质上,网站应该能够将事件添加到用户可以遵循的日历中,但不会在每个用户的日历中添加事件。

I'm trying to connect events withing py project to google calendar. my application doesn't used google login as it is intended for only a small group of people. I've been looking for hours on how to get it done and it doesnt work. Any help is appreciated.

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)

Ideally, I would use a service account so that users dont have to log in to google. Maybe someone knows a better solution than this but essentially the website should be able to add events to a calendar that users can follow but not add events to each user's calendar.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ま柒月 2025-02-07 12:10:06

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

就您的代码的服务帐户而言,使用Google Workspace帐户记住了使用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('[email protected]')

The main cause of your issue is you appear to be trying to mix service account authorization and installed application authorizaotn in the same code.

As far as the service accounts part of your code goes remember for service accounts with Google calendar with a google workspace account. Make sure you have properly configured the delegation to the user on your domain you want the service account to delegate as.

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('[email protected]')
千纸鹤带着心事 2025-02-07 12:10:06

在查看每个地方找到答案的地方之后。我将其发布到所需的大多数信息

感谢您的帮助

After looking every where i found the answer. I posted it under Google Calendar Integration with Django because thats where i got the majority of the info needed

Thanks for the help

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文