一意性制約はユーザー名にあるため、それをデータストアのキーとして使用し、トランザクションを使用する必要があります。
def txn():
key = ndb.Key(Member, username)
member = key.get()
if member is not None:
raise CustomAlreadyExistsException(member) # This will abort txn
member = Member(
id=username,
Pid=self.request.get('Pid'),
email=self.request.get('email'),
...)
member.put()
ndb.transaction(txn)
これにより、ユーザー名を登録できるのは 1 人だけになります。
jQueryヘルパーはndb.Key(Member, userid).get()
、結果が得られるかどうかを確認します。GET はトランザクションではありません。
可用性を確認した後にユーザー名を「予約」するクライアント側の使いやすさを向上させるには、Daniel が提案したように memcached を使用できますが、私は YAGNI を呼び出し、複雑さをスキップし、フォームを送信した後に一部の人に検証エラーが発生するようにします。memcached はベスト エフォートであり、何も保証しないことに注意してください。
複数のフィールドで一意性を保証する必要がある場合は、それらのモデル クラスを追加し、クロス グループ (XG) トランザクションをチェックインする必要があります。
class Pid(ndb.Model):
member = ndb.KeyProperty()
class Email(ndb.Model):
member = ndb.KeyProperty()
class Member(ndb.Model):
pid = ndb.KeyProperty()
email = ndb.KeyProperty()
@property
def pid_value(self):
return self.pid.id()
@property
def email_value(self):
return self.email.id()
def txn():
member_key = ndb.Key(Member, username)
pid_key = ndb.Key(PersonalId, self.request.get('Pid'))
email_key = ndb.Key(Email, self.request.get('email'))
member, pid, email = ndb.get_multi([member_key, pid_key, email_key])
if member is not None or pid is not None or email is not None:
raise CustomAlreadyExistsException(member, pid, email) # This will abort txn
# Create instances referencing each other
email = Email(key=email_key, member=member_key)
pid = Pid(key=pid_key, member=member_key)
member = Member(
key=member_key,
pid=pid_key,
email=email_key,
...)
ndb.put_multi([member, pid, email])
ndb.transaction(txn, xg=True)