我正在使用GoogleAppEngine尝试创建一个需要使用Twitter登录的简单应用。我的问题是,当我将用户重定向到我的情况下某种类型的“确认”页面/配置文件时 - 我收到了一个坏键错误,因为我将用户身份验证数据保存到我的db.Model中。
import logging
import webapp2
from google.appengine.ext import db
from google.appengine.ext.webapp import template
import urlparse
import oauth2 as oauth
consumer_key='MY_CONSUMER_KEY'
consumer_secret='SECRET_KEY'
request_token_url='https://api.twitter.com/oauth/request_token'
access_token_url='https://api.twitter.com/oauth/access_token'
authorize_url='https://api.twitter.com/oauth/authorize'
consumer=oauth.Consumer(consumer_key,consumer_secret)
client = oauth.Client(consumer)
screenname = ''
class Profile(db.Model):
twitter_id = db.StringProperty()
access_token = db.StringProperty()
access_token_secret = db.StringProperty()
twitter_user_name = db.StringProperty()
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.out.write(template.render("login.html", {}))
class SignInWithTwitter(webapp2.RequestHandler):
def get(self):
resp, content = client.request(request_token_url, "GET")
self.request_token = dict(urlparse.parse_qsl(content))
self.redirect((authorize_url +'?oauth_token='+ self.request_token['oauth_token']))
class ProfilePage(webapp2.RequestHandler):
def get(self):
logging.info("tst" + screenname)
self.profile = Profile.get(screenname)
self.response.out.write("<h1> Hello " + self.profile.screenname +"<h1>")
class AuthorizeTwitter(webapp2.RequestHandler):
def get(self):
oauth_verifier = self.request.get("oauth_verifier")
token = oauth.Token(self.request.get('oauth_token'), self.request.get('oauth_token_secret'))
token.set_verifier(oauth_verifier)
client = oauth.Client(consumer, token)
resp, content = client.request(access_token_url, "POST")
access_token = dict(urlparse.parse_qsl(content))
oauth_token = access_token['oauth_token']
oauth_token_secret = access_token['oauth_token_secret']
userid = access_token['user_id']
global screenname
screenname = access_token['screen_name']
logging.info(screenname)
profile = Profile.get_by_key_name(screenname)
if profile is None:
profile = Profile(key_name = screenname)
profile.twitter_id = userid
profile.access_token = oauth_token
profile.access_token_secret = oauth_token_secret
profile.twitter_user_name = screenname
profile.save()
self.redirect("/profile")
application = webapp2.WSGIApplication([
('/', MainHandler),
('/signin', SignInWithTwitter),
('/services/twitter/authorized', AuthorizeTwitter),
('/profile', ProfilePage),
], debug=True)
login.html只是一个将您重定向到/ signin
的按钮我得到的错误是:
BadKeyError: Invalid string key TwitterUserNameHere===. Details: Incorrect padding
还有一种方法可以在我将用户重定向到/ profile后获取当前配置文件吗?或者我是否需要使用我的全局screenname变量
继续访问我的数据库修改
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~howaggieru/1.371718316886323623/main.py", line 56, in get
self.profile = Profile.get(screenname)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 1238, in get
results = get(keys, **kwargs)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 1533, in get
return get_async(keys, **kwargs).get_result()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 1492, in get_async
keys, multiple = datastore.NormalizeAndTypeCheckKeys(keys)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/datastore.py", line 178, in NormalizeAndTypeCheckKeys
keys = [_GetCompleteKeyOrError(key) for key in keys]
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/datastore.py", line 2782, in _GetCompleteKeyOrError
key = Key(arg)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/datastore_types.py", line 371, in __init__
'Invalid string key %s. Details: %s' % (encoded, e))
BadKeyError: Invalid string key TwitterUsername===. Details: Incorrect padding
答案 0 :(得分:0)
回溯显示您的错误发生在ProfilePage
。现在,在AuthorizeTwitter
profile = Profile.get_by_key_name(screenname)
你正确地做ProfilePage
- 但在profile = Profile.get(screenname)
你做get_by_keyname
。这假设“screenname”是整个字符串键,它不是,因此是错误。在那里也使用{{1}}。
将屏幕名称保存为模块级全局会在一次有多个用户时引发各种问题。相反,您应该将其作为URL参数传递:您将从授权处理程序重定向到配置文件一,因此您应该将Twitter句柄作为URL参数传递给配置文件功能。 webapp2文档展示了如何做到这一点。