2011-01-07 54 views
2

基本的には、ユーザー名、ID、および日付が設定されているデータ構造です。それから私はそれがユーザー "テキスト"とそれが変更された日付を持っている "サブ構造"が欲しいです。ユーザーはこのテキストの複数のインスタンスを持ちます。Google App Engine Python Datastore

class User(db.Model): 
    ID = db.IntegerProperty()   
    name = db.StringProperty() 
    datejoined = db.DateTimeProperty(auto_now_add=True) 

class Content(db.Model): 
    text = db.StringProperty() 
    datemod= db.DateTimeProperty(auto_now_add = True) 

コードは正しく設定されていますか?

答えて

4

あなたが持つ1つの問題は、User.IDをユニークにすることが重要でないことです。問題は、データベースへの2回の書き込みが異なるシャード上で発生する可能性があることです。一意性制約に一致する既存のエントリをほぼ同時にチェックし、noneを見つけてから、(ユニークなプロパティに関して)無効なデータベース状態です。これを解決するために、Appengineは、特定のデータストアエンティティが常に同じ物理マシンに配置されることを保証する手段を提供します。

これを行うには、エンティティキーを使用して、エンティティの編成方法をGoogleに伝えます。ユーザー名が一意であることを想定します。 Userを次のように変更してください。

class User(db.Model): 
    datejoined = db.DateTimeProperty(auto_now_add=True) 

はい、それは本当です。これはキーで使用されるため、ユーザー名はありませんので、別途表示する必要はありません。あなたが好きなら、あなたはこれを行うことができます...

class User(db.Model): 
    datejoined = db.DateTimeProperty(auto_now_add=True) 

    @property 
    def name(self): 
     return self.key().name() 

Userのインスタンスを作成するには、あなたが今、少し違う何かをする必要があり、あなたは、initメソッドでkey_nameを指定する必要があります。

someuser = User(key_name='john_doe') 
... 
someuser.save() 

まあ、本当にユーザーが互いを上書きしないことを確認するには、あなたがトランザクションでユーザー作成をラップする必要があります。 、

someuser = User.get_by_key_name('john_doe') 

次へ:、その後

def create_user(username): 
    checkeduser = User.get_by_key_name(username) 
    if checkeduser is not None: 
     raise db.Rollback, 'User already exists!' 
    newuser = User(key_name=username) 
    # more code 
    newuser.put() 

あなただけのこの操作を行うユーザーを見つけるには、このよう

db.run_in_transaction(create_user, 'john_doe') 

でそれを呼び出す:まずneccesaryチェックを行う関数を定義しますコンテンツをユーザーに関連付ける方法と、その逆の方法が必要です。 1つの解決策は、ユーザをコンテンツの親として宣言することによって、コンテンツをユーザと同じエンティティグループに入れることである。これを行うには、あなたは、すべてのコンテンツを変更する必要はありませんが、あなたは(あなたがユーザーでやったくらいのように)少し違っそれを作成します。

somecontent = Content(parent=User.get_by_key_name('john_doe')) 

ので、コンテンツアイテム与え、あなたがルックアップすることができますユーザはそのキーを調べることによって:

逆に言えば、特定のユーザのすべてのコンテンツを検索することは少し難解です。

allcontent = Content.gql('where ancestor is :user', user=someuser).fetch(10) 
+0

これはまさに私が探しているものです! –

+0

@TokenMacGuy: 'newuser.save()'によって、 'newuser.put()'を意味しますか? – Kit

1

はい、ドキュメントがさらに必要な場合は、データベースタイプについてはhere、モデルクラスについてはhereを確認できます。

1

代わりの解決方法は、参照プロパティを使用することです。

class User(db.Model): 
     name = db.StringProperty() 
     datejoined = db.DateTimeProperty(auto_now_add=True) 

    class Content(db.Model): 
     user = db.ReferenceProperty(User,collection_name='matched_content') 
     text = db.StringProperty() 
     datemod= db.DateTimeProperty(auto_now_add = True) 

    content = db.get(content_key) 
    user_name = content.user.name 

    #looking up all of the content for a particular user 
    user_content = content.user.matched_content 

    #create new content for a user 
    new_content = Content(reference=content.user) 
+1

データ型の関連付けには適していますが、重複したユーザー名を可能にする競合状態からユーザーを保護することはできません。 – SingleNegationElimination

+0

コメントありがとうございました –

関連する問題