您将遇到的一个问题是使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)
这正是我所期待的! – 2011-01-07 03:55:46
@TokenMacGuy:通过`newuser.save()`,你的意思是`newuser.put()`? – Kit 2011-07-25 13:34:10