2012-12-15 59 views
2

我正在嘗試爲用戶創建一個簡單的註冊表。爲了使這個註冊是一致的,我不能允許註冊兩個用戶使用相同的用戶名,因爲默認查詢的最終一致性。我知道發生這種情況的機率幾乎爲零,但我希望我的實施能夠保持穩定。我已經實現了應該保持一致的祖先查詢,但是當我發佈我的應用程序並進行測試時,如果我時間正確,我可以使用相同的用戶名註冊2個用戶。使用GAE數據庫進行註冊驗證的強一致性查詢

def user_parent(group = 'default'): 
key = ndb.Key('users', group) 
return key 

class User(ndb.Model): 
    username = ndb.StringProperty(required = True) 
    email = ndb.StringProperty(required = True) 
    password = ndb.StringProperty(required = True) 

@classmethod 
def register(cls, username, password, email): 
    return User(parent = user_parent(), 
       username = username, 
       password = password, 
       email = email) 

@classmethod 
def by_name(cls, name): 
    return User.query(User.username == name, ancestor = user_parent()).get() 

@classmethod 
def by_id(cls, uid): 
    return User.get_by_id(uid, parent = user_parent()) 

@classmethod 
def by_email(cls, email): 
    logging.error(User.query(User.email == email, ancestor = user_parent()).get()) 
    return User.query(User.email == email, ancestor = user_parent()).get() 

@classmethod 
def login(cls, user, password): 
    u = cls.by_name(user) 
    if u and u.password == password: 
     return u 

我用reg_submit執行一個Ajax請求,我很新的節目,並懷疑這是去它的最佳解決方案,但這個想法是,在這裏,我與驗證的用戶模型進行通話類。

if reg_submit == 'True': 
     reg_email = self.request.get('reg_email') 
     reg_user = self.request.get('reg_user') 
     reg_password = self.request.get('reg_password') 
     reg_verify = self.request.get('reg_verify') 

     valid = True 
     if not valid_usr(reg_user): 
      valid = False 
      self.write('user') 
      return 
     if not valid_mail(reg_email): 
      valid = False 
      self.write('mail') 
      return 

     if User.by_email(reg_email): 
      valid = False 
      self.write('mail') 
      return 

     if User.by_name(reg_user): 
      valid = False 
      self.write('user') 
      return 

     if not valid_pass(reg_password): 
      valid = False 

     if reg_password != reg_verify: 
      valid = False 

     if valid: 
      t = User.register(reg_user, reg_password, reg_email) 
      t.put() 
      self.login(t) 
      self.redirect('/') 

,我通過提出強烈一致的查詢明白了什麼,是上述查詢將不會執行,直到每一個上我的數據庫複製將被更新的機器。

如何獲得強烈一致的查詢,其中兩個用戶同時註冊了相同的用戶名,其中一個用戶不能這樣做。

回答

1

您需要在事務中運行check-query和put。與NDB這樣做的文檔是here

1
Model.get_or_insert (key_name, **kwds) 

試圖獲取模型種類與給定鍵 名的實體。如果它存在,get_or_insert()只是返回它。如果不存在 ,則會創建,存儲並返回具有kwds 中的給定種類,名稱和參數的新實體。

get和後續(可能)放置操作被包裝在 事務中以確保原子性。這意味着get_or_insert()將不會覆蓋現有的實體,並且將插入一個新的實體,如果 ,並且只有在沒有給定種類和名稱的實體存在的情況下。

Get Or Insert

使用用戶名作爲key_name。設置你的模型,使其具有默認值,例如「new = True」,並檢查當你得到模型時,看看它是剛創建還是已經存在,當你問它。當你配置模型並保存時,設置「new = False」。

+0

我決定去一個交易,因爲我必須同時驗證用戶名和電子郵件(以及據我所知,此方法只需要一個key_name),以避免兩個字段中的數據翻倍。我相信這種方法在將來會派上用場,所以感謝你的迴應。 –

+0

沒問題。事實上,get_or_insert在事務內部運行,只是一個簡短的方法,但我明白你的觀點。 –

相關問題