2013-08-19 9 views
11

NDBモデルには、emailpasswordという2つのプロパティが含まれています。 emailの2つのレコードをデータベースに追加しないようにするにはどうすればいいですか?リレーショナルデータベースのように、NDBはプロパティに対してUNIQUEオプションを持っていません。NDBデータベースのプロパティの一意性を維持する

新しいemail 2つの並列プロセスが両方同時にチェックを行うことができ、それぞれが同じemailを追加するため—が、私は満足しません追加する前に、データベースに存在しないことを確認します。

私はトランザクションがここで助けになるとは思っていませんが、私はいくつかのマニュアルを読んだ後、この印象を受けています。たぶん同期トランザクション?一度に1つを意味するのでしょうか?

答えて

6

電子メールでエンティティのキ​​ーを作成し、get_or_insertを使用して存在するかどうかを確認します。

Also read about keys , entities.

#ADD 
key_a = ndb.Key(Person, email); 
person = Person(key=key_a) 
person.put() 

#Insert unique  
a = Person.get_or_insert(email) 

modelsまたはあなただけ確認したい場合は

#ADD 
key_a = ndb.Key(Person, email); 
person = Person(key=key_a) 
person.put() 

#Check if it's added 
new_key_a =ndb.Key(Person, email); 
a = new_key_a.get() 
if a is not None: 
    return 

注意してください。電子メールを変更することは本当に難しいでしょう(新しいエントリーを作成し、すべてのエントリーを新しい親にコピーする必要があります)。

メールを別のエンティティに保存し、そのユーザーをその親にする必要があるかもしれません。

もう1つの方法は、取引を使用してメールのプロパティを確認することです。途中でのトランザクションの作業:最初にコミットが勝つ第一です。 2人のユーザーが電子メールをチェックすると、最初の(幸運な)人のみが成功するというコンセプトなので、データは一貫しています。

+0

get_or_insert()を使用すると、私は新しいレコードを追加したか、既存のレコードを取得したのかわかりません。 – Graduate

+1

電子メールを変更すると痛みを感じます** ...またはそれ以上...できません:)電子メールの場合、それは良い解決策ではありません。 – Lipis

+0

@大学院生はそれを 'key_a'とするべきです。 –

4

おそらくあなたはこれを処理できるwebapp2認証モジュールを探しています。このようにインポートすることができますimport webapp2_extras.appengine.auth.models。完全な例については、hereを参照してください。私もこの問題に遭遇し、そして上記溶液は私の問題を解決していなかった

2

  • キーそれを作るには(私は将来的に変更可能にプロパティを必要とする)私の場合には受け入れられなかった
  • 電子メールプロパティでトランザクションを使用するとAFAIKが機能しません(トランザクション内のキー以外の名前についてクエリを実行できないため、電子メールがすでに存在するかどうかはチェックできません)。

プロパティを持たない別個のモデルと、キー名として固有のプロパティ(電子メールアドレス)を作成しました。メインモデルでは、メールを文字列として保存するのではなく、メールモデルへの参照を保存します。次に、私は 'change_email'に、キーで電子メールを検索して一意性をチェックするトランザクションを作成できます。

0

これは私が遭遇したことでもあり、@ Remkoの解決策のバリエーションを解決しました。私の主な問題は、与えられた電子メールで既存のエンティティをチェックすることです。電子メールアドレスをキーとして使用し、トークンを保持するプロパティを持つ別のモデルを追加しました。 get_or_insertを使用すると、返されたエンティティトークンは渡されたトークンに対してチェックされ、一致する場合はモデルが挿入されます。

import os 
from google.appengine.ext import ndb 

class UniqueEmail(ndb.Model): 
    token = ndb.StringProperty() 

class User(ndb.Model): 
    email = ndb.KeyProperty(kind=UniqueEmail, required=True) 
    password = ndb.StringProperty(required=True) 

def create_user(email, password): 
    token = os.urandom(24) 
    unique_email = UniqueEmail.get_or_insert(email, 
              token=token) 

    if token == unique_email.token: 
     # If the tokens match, that means a UniqueEmail entity 
     # was inserted by this process. 
     # Code to create User goes here. 
    # The tokens do not match, therefore the UniqueEmail entity 
    # was retrieved, so the email is already in use. 
    raise ValueError('That user already exists.') 
関連する問題