【问题标题】:Appengie Oauth: Spreadsheet api client.get_spreadsheets() returns errorAppengie Oauth:电子表格 api client.get_spreadsheets() 返回错误
【发布时间】:2014-09-30 10:54:13
【问题描述】:

尝试在 Google Appengine 中使用 oauthGData 列出 google 电子表格。但我收到以下错误。我的代码有什么问题吗?

请指教。

File "/home/RKS/Appengine/test/main.py", line 99, in get
    feed = client.get_spreadsheets()
  File "/home/RKS/Appengine/test/gdata/spreadsheets/client.py", line 78, in get_spreadsheets
    desired_class=desired_class, **kwargs)
  File "/home/RKS/Appengine/test/gdata/client.py", line 640, in get_feed
    **kwargs)
  File "/home/RKS/Appengine/test/gdata/client.py", line 278, in request
    version=get_xml_version(self.api_version))
  File "/home/RKS/Appengine/test/atom/core.py", line 520, in parse
    tree = ElementTree.fromstring(xml_string)
  File "<string>", line 125, in XML
ParseError: no element found: line 1, column 0

代码:

#!/usr/bin/env python

import webapp2
import logging
from google.appengine.api import users

import gdata.auth
import gdata.gauth
import gdata.client
import gdata.service
import gdata.spreadsheets
import gdata.spreadsheets.client
import gdata.spreadsheets.data

SETTINGS = {
    'APP_NAME': 'hidden',  # intentionally hidden
    'CONSUMER_KEY': 'hidden',
    'CONSUMER_SECRET': 'hidden',
    'SCOPES': ['https://spreadsheets.google.com/feeds'],
    'CALLBACK_URL': '',
    'SIG_METHOD': gdata.auth.OAuthSignatureMethod.HMAC_SHA1
}

class FetchToken(webapp2.RequestHandler):
    def get(self):
        current_uid = users.get_current_user().user_id()
        if isinstance(gdata.gauth.AeLoad(current_uid), gdata.gauth.OAuthHmacToken):
            # the user has gone through the process before
            self.redirect('/')
        else:
              # the user has not gone through this process, or the authorization has expired or been revoked.
            SETTINGS['CALLBACK_URL'] = 'http://%s/HandleOAuthCallback' % self.request.host
            client = gdata.client.GDClient()
            request_token = client.GetOAuthToken(
                SETTINGS['SCOPES'],
                SETTINGS['CALLBACK_URL'],
                SETTINGS['CONSUMER_KEY'],
                consumer_secret=SETTINGS['CONSUMER_SECRET'])

            gdata.gauth.AeSave(request_token, current_uid)
            self.redirect(str(request_token.generate_authorization_url()))


class HandleOAuthCallback(webapp2.RequestHandler):
    def get(self):
        current_uid = users.get_current_user().user_id()
        client = gdata.client.GDClient()
        saved_request_token = gdata.gauth.AeLoad(current_uid)
        request_token = gdata.gauth.AuthorizeRequestToken(saved_request_token, self.request.uri)
        access_token = client.GetAccessToken(request_token)
        gdata.gauth.AeSave(access_token, current_uid)
        self.redirect('/')


class GetDocsList(webapp2.RequestHandler):
    def get(self):
        if not users.get_current_user():
            self.redirect(users.create_login_url('/'))
        else:
            current_uid = users.get_current_user().user_id()
            if isinstance(gdata.gauth.AeLoad(current_uid), gdata.gauth.OAuthHmacToken):
                # the user has gone through the process before

                access_token = gdata.gauth.AeLoad(current_uid)
                client = gdata.service.GDataService()

                oauth_input_params = gdata.auth.OAuthInputParams(
                    gdata.auth.OAuthSignatureMethod.HMAC_SHA1,
                    SETTINGS['CONSUMER_KEY'],
                    SETTINGS['CONSUMER_SECRET'])  # consumer_secret=

                oauth_token = gdata.auth.OAuthToken(
                    key=access_token.token,
                    secret=access_token.token_secret,
                    scopes=SETTINGS['SCOPES'],
                    oauth_input_params=oauth_input_params)

                client.SetOAuthToken(oauth_token)

                client = gdata.spreadsheets.client.SpreadsheetsClient()

                feed = client.get_spreadsheets()

            else:
                self.redirect('/FetchToken')


app = webapp2.WSGIApplication([('/HandleOAuthCallback', HandleOAuthCallback), ('/', GetDocsList), ('/FetchToken', FetchToken)], debug=False)

【问题讨论】:

  • Google DrEdit 教程包括 OAuth2。我发现它们是一个很好的起点。

标签: python google-app-engine oauth gdata google-spreadsheet-api


【解决方案1】:

我建议切换到 OAuth2,我的大部分答案都会解释如何通过这样做来解决您的问题。但是,在尝试切换到 OAuth2 之前,我建议您尝试这一行更改,这可能是您问题的快速解决方案。我会尝试的第一件事是向您的客户端添加标题,如下所示。

client.additional_headers = {
  'Authorization': 'Bearer %s' % access_token,
}

我有一个使用带有 OAuth2 的 GData 电子表格 API 的应用程序,并且需要添加该标头才能使其正常工作。如果我把那个标题去掉,我会得到一个像你描述的错误。

现在,回答: 在 App Engine 中使用 OAuth2 来做您想做的事情比您已经做过的事情还要简单。以下是它的完成方式。

首先创建一个 OAuth2 装饰器。 (我在答案末尾描述了在哪里创建您的客户端 ID 和客户端密码。)

from oauth2client.appengine import OAuth2Decorator
GlobalOAuth2Decorator = OAuth2Decorator(
  client_id=OAUTH2_CLIENT_ID,
  client_secret=OAUTH2_CLIENT_SECRET,
  scope='https://spreadsheets.google.com/feeds',
)

然后在创建请求处理程序时使用此装饰器。

class SpreadsheetHandler(webapp2.RequestHandler):
  @GlobalOAuth2Decorator.oauth_required
  def get(self):
    client = gdata.spreadsheet.service.SpreadsheetsService()
    client.additional_headers = {
      'Authorization': 'Bearer %s' % GlobalOAuth2Decorator.credentials.access_token,
    }

请注意,我使用的是 SpreadsheetsService 而不是 SpreadsheetsClient。这一直对我有用,虽然我没有尝试过 SpreadsheetsClient(客户端实际上可能更容易使用)。

创建此client 对象后,您可以根据需要使用它来读写电子表格。例如,sheets = client.GetSpreadsheetsFeeds() 将为您提供可以访问的电子表格列表。

最后,确保在创建应用程序时将 OAuth 处理程序包含在处理程序列表中:

app = webapp2.WSGIApplication([..., (GlobalOAuth2Decorator.callback_path, GlobalOAuth2Decorator.callback_handler())]

为了使 OAuth2 正常工作,您必须通过 https://console.developers.google.com 访问您的开发者控制台并 1) 选择您的应用,2) 从 Credentials 菜单中创建一个新的客户端 ID(这将为您生成一个客户端 ID 和密码)您)和 3)从同意屏幕菜单中为您的应用程序提供电子邮件地址和姓名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 1970-01-01
    相关资源
    最近更新 更多