我正在设计一个新的 AppEngine/Python HRD 应用程序。在此应用程序中,我需要确保每个注册用户都不能使用已分配给其他用户的名称,并且如果两个用户尝试在完全相同的时刻使用相同的用户名注册,则只有其中一个用户会被给予用户名。
如果我将所有用户名放在一个实体组中并使用事务来确保唯一性,那么在事务中写入用户名/对象可能会减慢所有注册过程。所以这种方法似乎不是一个好主意。
另一种选择是使用用户名作为 key ,其缺点是可能使用户以后难以更改其用户名。
在 AppEngine 中实现这一目标的最佳/标准方法是什么?
最佳答案
好的。
您不需要将所有用户名粘贴在一个大实体组中来保证一致性。
将用户名作为管理登录的数据存储实体的 key 。
然后在事务中。
- 尝试使用用户名作为 key 进行获取(这是一致的操作) 如果你找到它,那么显然它不可用
- 如果未找到,则创建新的登录实体。
顺便说一句,如果您使用电子邮件地址,那么很可能意味着永远不会发生冲突。我不确定为什么可见的昵称需要是唯一的,但你可能有一个很好的理由。
每个实际用户对象都可以有一个系统生成的唯一 ID(这是登录实体的单独实体)。
如果您真的很偏执,那么请考虑使用 memcache CAS 操作来有效地充当用户名 key 的锁定并防止同时操作,尽管我认为没有必要。
实体可能看起来像
class Login(ndb.Model):
# other stuff neede for authentication etc..
user = ndb.KeyProperty(User)
@ndb.transactional(xg=True)
@classmethod
def create_login(cls,username):
# maybe pass in extra user details
key = ndb.Key(cls, keyname)
login = key.get()
if login:
raise DuplicateUsernameError(username)
login = Login(key_name=username)
user = User.create_user(login=login.key)
login.user = user.key
login.put()
return (login,user)
class User(ndb.Model):
login = ndb.KeyProperty(Login) # this property is only for convenience.
nickname = ndb.StringProperty()
# etc
@classmethod
def create_user(cls,login_key):
# yes you would pass in more user stuff.
user = cls(login=login_key)
user.put()
# the unique user key is system generated.
return user
这意味着只需要一个 get() 来获取登录信息,然后再获取其余的用户详细信息,但比查询便宜/更快。这还意味着如果您确实想要这样的功能,则可以随着时间的推移更改登录名/代码,而不会破坏实际的用户实体。或者可能支持单个用户的多种登录方法 - 即 facebook 和 twitter。这还意味着随着时间的推移,登录实体可以被删除并由其他人重新使用登录,并且如果需要系统完整性/历史记录,则用户实体可以保留。
关于python - App Engine Python - 如何确保用户使用唯一的用户名注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24085216/