2012-06-25 33 views
5

因此,我正在为jinja2模板平台上的google appengine的python编写应用程序。我已经得到OpenID在我的网站上工作得很好,它允许用户登录,我可以在右上角显示他们的电子邮件/ ID。给openid用户附加信息

现在我希望用户拥有自己的用户名并能够存储一些关于他们的附加数据,例如网站访问和某些帖子到网站的某些区域。

我知道我需要在数据库中用用户和所有东西创建一个表,但是用OpenID做到这一点的正确方法是什么。我想在有人第一次登录时自动创建用户,但我不确定如何有效地完成此操作。我想我可以通过将它们重定向到一个页面来管理它,这个页面在数据库中检查它们的federated_identity,如果它已经存在,它只是将它们重定向到主页,但是如果不存在,它会创建一个新用户。

有没有一种更有效的方式,以便每次有人登录时我都不查询数据库,或者是一个相当不错的方式来做到这一点?

回答

6

您是对的,您必须创建您自己的用户模型并存储额外信息以及您在应用程序中的任何业务逻辑。所有你需要做的是用额外的usernamename一起存储(例如federated_id)独有的东西,等

与OpenID登录后,你会检查是否该特定federated_id是在你的数据存储,你会返回该特定的user_db,或者使用默认值创建一个新的并返回新创建的user_db

重要的是,在您的请求中,您将始终处理您自己的user_db实体,而不是users.get_current_user(),因为这基本上是只读和有限的。

下面是一个完整的例子,这也显示了与get_user()功能,如果用户登录和None否则,将返回自己的user_db实体base handler class。如果用户要登录的第一次,一个新的USER_DB实体与一些默认值(nameusernameemailadminfederated_id)创建:

from google.appengine.api import users 
from google.appengine.ext import ndb 
import webapp2 

class User(ndb.Model): 
    name = ndb.StringProperty(required=True) 
    username = ndb.StringProperty(required=True) 
    email = ndb.StringProperty() 
    federated_id = ndb.StringProperty() 
    admin = ndb.BooleanProperty() 

class BaseHandler(webapp2.RequestHandler): 
    def get_user_db(self): 
    federated_user = users.get_current_user() 
    if not federated_user: 
     return None 
    user_db_qry = User.query(User.federated_id == federated_user.user_id()) 
    user_db_list = user_db_qry.fetch(1) 
    #If that returns non empty list, then return the first element which is the user_db 
    if user_db_list: 
     return user_db_list[0] 

    #Otherwise create a new user_db entity, with default values and return 
    user_db = User(
     name=federated_user.nickname().title(), 
     username=federated_user.nickname(), 
     email=federated_user.email(), 
     federated_id=federated_user.user_id(), 
     admin=users.is_current_user_admin(), 
    ) 
    user_db.put() 
    return user_db 

class MainHandler(BaseHandler): 
    def get(self): 
    self.response.headers['Content-Type'] = 'text/html' 
    if self.get_user_db(): 
     self.response.out.write('Hello, %s!</br>' % self.get_user_db().name) 
     self.response.out.write('<a href="%s">Logout</a>' % (users.create_logout_url(self.request.uri))) 
    else: 
     self.response.out.write('Hello, stranger!<br>') 
     self.response.out.write('<a href="%s">Login</a>' % (users.create_login_url(self.request.uri))) 

app = webapp2.WSGIApplication([('/', MainHandler)], 
           debug=True) 

有很多不同的方法解决这个问题,但我认为这是一个很好的开始来获得这个想法。

+0

好吗很好,谢谢你今天下午测试一下,看看它是如何去 – clifgray

+0

你能解释一下这条线做:user_db_list = User.query(User.federated_id == federated_user.user_id())获取( 1) – clifgray

+0

@clifgray该行正在从您自己的模型中检索具有特定federated_id的用户...如果结果不是空列表,那么我们有一个赢家.. otherwiser我们必须创建一个实体,然后返回它.. – Lipis