2

ユーザー用の簡単な登録簿を作成しようとしています。その登録の一貫性を保つために、デフォルト クエリの最終的な一貫性を考慮して、同じユーザー名で 2 人のユーザーを登録することはできません。かなりのトラフィックがあっても、その可能性はほぼ 0 であることを知っています。実装をしっかりしたものにしたいと考えています。強力な一貫性を持つ祖先クエリを実装しましたが、アプリを公開してテストすると、タイミングが合えば同じユーザー名で 2 人のユーザーを登録できます。

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リクエストを実行します。私はプログラミングに非常に慣れていないため、これが最善の解決策であるとは思えませんが、ここではUserモデルクラスへの呼び出しで検証するという考えです。

    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('/')

クエリを強力に一貫性のあるものにすることで理解していることは、データベースが複製されているすべてのマシンが更新されるまで、上記のクエリは実行されないということです。

2 人のユーザーが同時に登録し、同じユーザー名を使用して、そのうちの 1 人が登録できない場合に、強力に一貫性のあるクエリを実行するにはどうすればよいですか。

4

2 に答える 2

1
Model.get_or_insert (key_name, **kwds)

指定されたキー名を持つモデルの種類のエンティティを取得しようとします。存在する場合、get_or_insert()は単にそれを返します。存在しない場合は、kwdsで指定された種類、名前、およびパラメーターを持つ新しいエンティティが作成され、保存されて返されます。

getおよび後続の(可能な)put操作は、原子性を確保するためにトランザクションにラップされます。これは、get_or_insert()が既存のエンティティを上書きすることはなく、指定された種類と名前のエンティティが存在しない場合にのみ、新しいエンティティを挿入することを意味します。

取得または挿入

ユーザー名を。として使用しますkey_name。モデルをデフォルトになるように設定し、「new = True」と言って、モデルを元に戻したときに、モデルが作成されたばかりか、要求したときにすでに存在していたかを確認します。モデルを構成して保存し直すときは、「new=False」に設定します。

于 2012-12-15T21:56:20.700 に答える
1

check-query と put をトランザクション内で実行する必要があります。NDB でこれを行うためのドキュメントはこちらです。

于 2012-12-15T21:56:36.410 に答える