谷歌与Django的日历集成

pas*_*sql 5 python django google-calendar-api oauth-2.0

是否有一个完全成熟的基于Django的Google Calendar集成示例?我正在阅读Google的示例页面,但它们底部的链接已过时.

我特别喜欢刷新令牌,因为Google的例子只关注如何获取访问令牌.这就是我到目前为止所拥有的:

@staff_member_required
def authorize_access(request):
    return redirect(get_flow(request).step1_get_authorize_url())

@staff_member_required
def oauth2_callback(request):
    credentials = get_flow(request).step2_exchange(request.GET['code'])

    store = get_store()
    store.put(credentials)
    credentials.set_store(store)

    return redirect('...')

def get_flow(request):
    flow = client.flow_from_clientsecrets(os.path.join(CREDENTIAL_DIR, CLIENT_SECRET_FILE),
                                      SCOPES,
                                      redirect_uri='%s://%s/google-calendar/oauth2-callback/' % (request.META['wsgi.url_scheme'], request.META['HTTP_HOST'],))
    flow.params['access_type'] = 'offline'
    flow.params['approval_prompt'] = 'force'

    return flow

def get_store():
    return oauth2client.file.Storage(os.path.join(CREDENTIAL_DIR, ACCESS_TOKEN_FILE))

def has_valid_api_credentials():
    credentials = get_store().get()
    return credentials is not None

def build_service():
    credentials = get_store().get()

    if not credentials:
        return None
    elif credentials.access_token_expired:
        http = credentials.refresh(httplib2.Http())
        http = get_store().get().authorize(http)
    else:
        http = credentials.authorize(httplib2.Http())

    service = discovery.build('calendar', 'v3', http=http)

    return service

def create_events(rental_request):
    service = build_service()

    event = service.events().insert(...).execute()
Run Code Online (Sandbox Code Playgroud)

pas*_*sql 10

研究了很多不同的方法,我发现服务器到服务器的身份验证就是我想要的.这样,没有用户必须明确授予权限,并且获取的auth-token不必更新.相反,使用服务帐户,服务器可以自己进行调用.

在开始编码之前,您必须设置此类服务帐户并将其添加到您希望服务帐户访问的日历中.谷歌已经写下来的三个步骤来创建一个帐户这里.然后,转到https://calendar.google.com,在屏幕左侧找到要与新服务帐户共享的日历,然后点击旁边的三角形.从下拉菜单中选择日历设置.这会将您带到一个屏幕,您可以在其中找到稍后需要的日历ID(将其写下来),并在顶部显示一个选项卡以共享对日历的访问权限.当"人"从服务帐户插入电子邮件地址时,为其分配相应的权限并单击"保存"(如果未单击"保存",则不会添加服务帐户).

这个代码实际上非常优雅:

import os
from datetime import timedelta
import datetime
import pytz

import httplib2
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials

service_account_email = 'XXX@YYY.iam.gserviceaccount.com'

CLIENT_SECRET_FILE = 'creds.p12'

SCOPES = 'https://www.googleapis.com/auth/calendar'
scopes = [SCOPES]

def build_service():
    credentials = ServiceAccountCredentials.from_p12_keyfile(
        service_account_email=service_account_email,
        filename=CLIENT_SECRET_FILE,
        scopes=SCOPES
    )

    http = credentials.authorize(httplib2.Http())

    service = build('calendar', 'v3', http=http)

    return service


def create_event():
    service = build_service()

    start_datetime = datetime.datetime.now(tz=pytz.utc)
    event = service.events().insert(calendarId='<YOUR EMAIL HERE>@gmail.com', body={
        'summary': 'Foo',
        'description': 'Bar',
        'start': {'dateTime': start_datetime.isoformat()},
        'end': {'dateTime': (start_datetime + timedelta(minutes=15)).isoformat()},
    }).execute()

    print(event)
Run Code Online (Sandbox Code Playgroud)

我正在使用oauth2client 2.2.0版(pip install oauth2client).

我希望这个答案有帮助:)

  • 非常感谢!如今,谷歌默认使用 JSON 密钥格式,因此您的代码可以从 `credentials = ServiceAccountCredentials.from_p12_keyfile(service_account_email=service_account_email, filename=CLIENT_SECRET_FILE,scopes=SCOPES)` 改编为 `credentials = ServiceAccountCredentials.from file_name_keyfile JSON 格式的密钥&gt;,scopes=SCOPES)` (2认同)

小智 7

这里请注意:尽管代码有效,但根据https://github.com/googleapis/google-auth-library-python/blob/7a8641a7f0718c0dce413436f23691e8590face1/docs/index.rst, oauth2client 最近已被弃用,以支持 google-身份验证库 - https://github.com/googleapis/google-auth-library-python/tree/edfe24602051969e32917e82bcedd2bace43e260

您可以在这里找到新库的文档 - https://google-auth.readthedocs.io/en/latest/user-guide.html

要使用新库,代码可以编写为

import datetime
from datetime import timedelta

import pytz

from google.oauth2 import service_account

from googleapiclient.discovery import build

service_account_email = "app-calendar@xxxxxxxxx.iam.gserviceaccount.com"
SCOPES = ["https://www.googleapis.com/auth/calendar"]

credentials = service_account.Credentials.from_service_account_file('google_calendar_credential.json')
scoped_credentials = credentials.with_scopes(SCOPES)


def build_service():
    service = build("calendar", "v3", credentials=scoped_credentials)
    return service


def create_event():
    service = build_service()

    start_datetime = datetime.datetime.now(tz=pytz.utc)
    event = (
        service.events()
        .insert(
            calendarId="primary",
            body={
                "summary": "Foo 2",
                "description": "Bar",
                "start": {"dateTime": start_datetime.isoformat()},
                "end": {
                    "dateTime": (start_datetime + timedelta(minutes=15)).isoformat()
                },
            },
        )
        .execute()
    )

    print(event)

create_event()
Run Code Online (Sandbox Code Playgroud)

由于我没有足够的声誉来发布此评论,因此我将其发布为单独的帖子


Joe*_*der 5

由于这篇文章是很久以前发布的,所以我想分享我的 2020 版本。感谢这篇文章。对我实现目标有很大帮助。

import datetime
from datetime import timedelta

import pytz
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials

service_account_email = "INSERT_HERE"
SCOPES = ["https://www.googleapis.com/auth/calendar"]
credentials = ServiceAccountCredentials.from_json_keyfile_name(
    filename="FILENAME.json", scopes=SCOPES
)


def build_service():
    service = build("calendar", "v3", credentials=credentials)
    return service


def create_event():
    service = build_service()

    start_datetime = datetime.datetime.now(tz=pytz.utc)
    event = (
        service.events()
        .insert(
            calendarId="CALENDARID@group.calendar.google.com",
            body={
                "summary": "Foo",
                "description": "Bar",
                "start": {"dateTime": start_datetime.isoformat()},
                "end": {
                    "dateTime": (start_datetime + timedelta(minutes=15)).isoformat()
                },
            },
        )
        .execute()
    )

    print(event)

create_event()
Run Code Online (Sandbox Code Playgroud)