2011-01-07 108 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) 
相关问题