2011-01-07 86 views
2

基本上我試圖做的是一個數據結構,它有用戶名,id和datejoined。然後我想要一個「子結構」,它有用戶「文本」和它被修改的日期。用戶將擁有多個此文本實例。谷歌應用程序引擎Python數據存儲

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

您將遇到的一個問題是使User.ID獨一無二將是不平凡的。問題在於,對數據庫的兩次寫入可能發生在不同的分片上,它們大致同時檢查與唯一性約束相匹配的現有條目並且找不到任何條目,然後創建相同的條目(關於唯一屬性),然後您有一個無效的數據庫狀態。爲了解決這個問題,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() 

嗯,真的要確保用戶不會相互覆蓋,所以您需要將用戶創建包裝在事務中。首先定義,做的neccesary檢查功能:

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

要查找用戶,你只是這樣做:

someuser = User.get_by_key_name('john_doe') 

接下來,您需要某種方式將內容與用戶相關聯,反之亦然。一種解決方案是通過將用戶聲明爲內容的父項,將內容放入與用戶相同的實體組中。要做到這一點,你不需要做任何改動的內容,但你創建一個有點不同(就像你與用戶所做的那樣):

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

所以,對於一個內容項,你可以看一下用戶通過檢查其關鍵字:

someuser = User.get(somecontent.key().parent()) 

反過來,查找特定用戶的所有內容只是有點棘手。

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

這正是我所期待的! – 2011-01-07 03:55:46

+0

@TokenMacGuy:通過`newuser.save()`,你的意思是`newuser.put()`? – Kit 2011-07-25 13:34:10

1

是的,如果你需要更多的文檔,你可以檢查here數據庫類型和here關於你的模型類的更多信息。

1

您可能會看到的替代解決方案是使用referenceproperty。

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) 
相關問題