如何更改Google表格电子表格的所有者?

时间:2017-10-11 05:17:37

标签: python google-sheets permissions google-sheets-api

通过以下内容,我可以在Google表格中以编程方式创建电子表格,但表格的所有者是开发人员帐户(以“gserviceaccount.com”结尾的疯狂字符串),而我的普通帐户无法查看电子表格。为了将Google用户添加到读/写权限,我还需要做些什么?

from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient import discovery

# ... json_key is the json blob that has the credentials
scope = ['https://spreadsheets.google.com/feeds']
credentials = ServiceAccountCredentials.from_json_keyfile_dict(json_key, scope)
service = discovery.build('sheets', 'v4', credentials=credentials)

spreadsheet = {
  "properties": {"title": "my test spreadsheet"}
}

service.spreadsheets().create(body=spreadsheet).execute()

编辑:
我尝试将范围更改为['https://www.googleapis.com/auth/drive'],但下面的答案仍然不适用于我。我跑的时候

print [xx for xx in dir(service) if not xx.startswith('_')]

我得到了

['new_batch_http_request', u'spreadsheets']

换句话说,permissions()不是service中的方法,因为我已定义服务。我应该做些什么?

3 个答案:

答案 0 :(得分:3)

我从阅读Chris留下的评论中想出来了。他的评论中缺少的是你实际上需要在他的drive_service中使用特定的范围。请注意我用于构建不同对象的范围更改:

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

key = '/path/to/service_account.json'

# Build 'Spreadsheet' object

spreadsheets_scope = [ 'https://www.googleapis.com/auth/spreadsheets' ]
sheets_credentials = ServiceAccountCredentials.from_json_keyfile_name(key, spreadsheets_scope)

sheets_service = build('sheets', 'v4', credentials=sheets_credentials)

# returns 'Spreadsheet' dict
# https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets#resource-spreadsheet
spreadsheet = sheets_service.spreadsheets().create(
    body={
        "properties": {
            'title': 'spreadsheets test',
        },
        "sheets": [],
    }
).execute()


# id for the created file
spreadsheetId = spreadsheet['spreadsheetId']
# url of your file
spreadsheetUrl = spreadsheet['spreadsheetUrl']

# Build 'Permissions' object
drive_scope = [ 'https://www.googleapis.com/auth/drive' ]
drive_credentials = ServiceAccountCredentials.from_json_keyfile_name(key, drive_scope)

drive_service = build('drive', 'v3', credentials=drive_credentials)

# returns 'Permissions' dict
permissions = drive_service.permissions().create(
    fileId=spreadsheetId,
    transferOwnership=True,
    body={
        'type': 'user',
        'role': 'owner',
        'emailAddress': 'example@email.com',
    }
).execute()

# apply permission 
drive_service.files().update(
    fileId=spreadsheetId,
    body={'permissionIds': [permissions['id']]}
).execute()

print ('\nOpen me:\n\n%s\n' % spreadsheetUrl)

所以逻辑是,电子表格资源'由build制作,包含其所有属性和工作表数据,所有者设置为您的服务帐户。接下来,一个“驱动资源”'这是使用permissions()方法的资源。 execute()会返回用于update()电子表格文件的新创建的权限 ID

答案 1 :(得分:1)

Service只是discovery.build调用结果的通用名称。在这种情况下,没有'权限'方法只是它在同一服务上不可用。如果不需要更改所有者,则以下代码就足够了。要添加具有读写权限的人,以下内容适用于我:

[...]

要实际更改所有者,必须设置转让所有权标志:

def grant_permissions(spreadsheet_id, writer):
    drive_service = discovery.build('drive', 'v3')

    permission = drive_service.permissions().create(
        fileId=spreadsheet_id,
        body={
            'type': 'user',
            'role': 'writer',
            'emailAddress': writer,
        }
    ).execute()

    drive_service.files().update(
        fileId=spreadsheet_id,
        body={'permissionIds': [permission['id']]}
    ).execute()

正在使用的服务帐户必须具有正确的权限。我相信那些对我有用的是在第一次创建服务帐户时检查套件盒。

答案 2 :(得分:0)

尝试使用Permissions: insert中的方法documentation。您将能够插入文件或团队驱动器的权限。

以下是文档中提供的sample code

from apiclient import errors
# ...

def insert_permission(service, file_id, value, perm_type, role):
  """Insert a new permission.

  Args:
    service: Drive API service instance.
    file_id: ID of the file to insert permission for.
    value: User or group e-mail address, domain name or None for 'default'
           type.
    perm_type: The value 'user', 'group', 'domain' or 'default'.
    role: The value 'owner', 'writer' or 'reader'.
  Returns:
    The inserted permission if successful, None otherwise.
  """
  new_permission = {
      'value': value,
      'type': perm_type,
      'role': role
  }
  try:
    return service.permissions().insert(
        fileId=file_id, body=new_permission).execute()
  except errors.HttpError, error:
    print 'An error occurred: %s' % error
  return None

使用Try it now测试实时数据并查看API请求和响应。

如需进一步阅读,请查看SO post