2012-06-25 71 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