2012-12-15 2 views
2

사용자를위한 간단한 레지스터를 만들려고합니다. 해당 레지스터가 일관성을 유지하기 위해 기본 쿼리의 최종 일관성을 고려하여 동일한 사용자 이름으로 두 명의 사용자를 등록하는 것을 허용 할 수 없습니다. 상당한 트래픽이 발생하더라도 그 일이 일어나는 확률은 거의 0입니다. 저는 구현이 견고해야합니다. 강하게 일관성이있는 조상 쿼리를 구현했지만 아직 내 앱을 게시하고 테스트 할 때 올바른 시간에 동일한 사용자 이름으로 2 명의 사용자를 등록 할 수 있습니다. 나는 아약스 요청을 수행 할 reg_submit를 사용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 

, 내가 프로그래밍에 매우 새로 온 사람이 그것에 대해 이동하는 가장 좋은 솔루션입니다 의심하지 않지만, 아이디어는 여기서 i는 사용자 모델을 만들어 전화로 확인한다는 것입니다 수업.

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

트랜잭션 내에서 확인 쿼리와 put을 실행해야합니다. NDB에서이 작업을 수행하기위한 문서는 here입니다.

1
Model.get_or_insert (key_name, **kwds) 

시도는 지정된 키 이름을 가진 모델의 종류의 실체를 얻을 수 있습니다. 존재하는 경우, get_or_insert()는 단순히 그것을 리턴합니다. 이 없으면 kwds 에 지정된 종류, 이름 및 매개 변수가있는 새 엔터티가 만들어지고 저장되고 반환됩니다.

반입 및 후속 (가능한) put 조작은 트랜잭션으로 래핑되어 원 자성을 보장합니다. Ths는 get_or_insert()가 이 기존 엔티티를 덮어 쓰지 않으며, 주어진 종류 및 이름의 엔티티가없는 경우에만 인 경우 새 엔티티를 삽입 함을 의미합니다.

Get Or Insert.

사용자 이름을 key_name으로 사용하십시오. 모델을 기본값으로 설정하고 "new = True"라고 말한 다음 모델을 다시 가져올 때 방금 생성되었는지 또는 요청했는지 이미 확인했는지 확인하십시오. 모델을 구성하고 다시 저장하면 "new = False"를 설정하십시오.

+0

두 필드의 데이터가 중복되지 않도록 사용자 이름과 이메일을 동시에 확인해야하므로 (이 방법은 하나의 key_name 만 사용한다는 것을 이해하는 한) 동시에 트랜잭션을 수행하기로 결정했습니다. 앞으로이 방법이 유용하게 쓰일 것이라고 확신합니다. 답장을 보내 주셔서 감사합니다. –

+0

문제 없습니다. 실제로 get_or_insert는 트랜잭션 내에서 실행되며 실제로는 짧은 방법입니다.하지만 당신의 요점을 보았습니다. –