Google应用程序引擎Python数据存储

Google应用程序引擎Python数据存储,python,google-app-engine,Python,Google App Engine,基本上,我试图创建一个数据结构,其中包含用户名、id和datejoined。然后我想要一个“子结构”,其中包含用户“文本”和修改日期。用户将拥有此文本的多个实例 class User(db.Model): ID = db.IntegerProperty() name = db.StringProperty() datejoined = db.DateTimeProperty(auto_now_add=True) class Content(db.Mod

基本上,我试图创建一个数据结构,其中包含用户名、id和datejoined。然后我想要一个“子结构”,其中包含用户“文本”和修改日期。用户将拥有此文本的多个实例

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)   

代码设置是否正确

是的,如果您需要更多文档,您可以检查数据库类型以及有关模型类的更多信息。

您将遇到的一个问题是,使
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()
要创建
用户的实例
,您现在需要做一些不同的事情,您需要在init方法中指定一个
键名

someuser = User(key_name='john_doe')
...
someuser.save()
实际上,您希望确保用户不会相互覆盖,因此需要将用户创建包装在事务中。首先定义一个执行必要检查的函数:

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')
接下来,您需要某种方式将内容与其用户关联,反之亦然。一种解决方案是通过将用户声明为内容的父级,将内容放入与用户相同的实体组中。要做到这一点,您根本不需要更改内容,但您创建内容的方式略有不同(就像您对用户所做的那样):

因此,给定一个内容项,您可以通过检查其键来查找用户:

someuser = User.get(somecontent.key().parent())
反过来说,查找某个特定用户的所有内容只是有点棘手

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

您可能看到的另一种解决方案是使用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)

这正是我要找的@TokenMacGuy:您所说的
newuser.save()
,是指
newuser.put()
?关联数据类型的良好解决方案,但不会保护您免受允许重复用户名的竞争条件的影响。
    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)