假设您有一个“用户”记录的概念,您希望将其存储在数据存储中。
class User (db.Model):
first_name = db.StringProperty()
last_name = db.StringProperty()
created = db.DateTimeProperty(auto_now_add=True)
twitter_oauth_token = db.StringProperty()
twitter_oauth_secret = db.StringProperty()
您几乎在使用用户对象时都会使用某些字段,例如first_name和last_name。
但是,有些字段只有一个用例,例如,twitter_oauth_token和twitter_oauth_secret,当95%的时间不需要它们时,打扰序列化和反序列化效率会有些低效。
因此,如果您拆分模型:
class User (db.Model):
first_name = db.StringProperty()
last_name = db.StringProperty()
created = db.DateTimeProperty(auto_now_add=True)
class UserTwitterOauth(db.Model):
oauth_token = db.StringProperty(required=True)
oauth_secret = db.StringProperty(required=True)
created = db.DateTimeProperty(auto_now_add=True)
你可以在UserTwitterOauth中为User提供一个ReferenceProperty,但这实际上是一对多的,因为没有什么能阻止每个用户使用多个UserTwitterOauth对象。您希望最多只有一个UserTwitterOauth与任何用户相关。你如何一对一地将这些模型联系起来?
答案 0 :(得分:6)
在这种特定情况下,您最好的选择可能是使UserTwitterOauth
实体成为具有众所周知密钥名称的User
实体的子实体,如下所示:
my_user = User(first_name="John", last_name="Smith")
my_user.put()
extra_info = UserTwitterOauth(parent=my_user, key_name="UserTwitterOauth")
extra_info.put()
您可以向User
类添加简单的方法或属性,以便于检索其他信息,并将UserTwitterOauth
的类方法添加为工厂方法,从而保留约定。
顺便提一下,请注意User
是实体的危险名称 - 用户API也有一个名为User
的类,除非您对导入非常小心,否则最终可能会引用当你打算引用另一个时,你就来了。
答案 1 :(得分:0)
在我看来,从Twitter访问令牌到用户的引用属性是最容易维护的。确实,许多访问令牌都可以引用用户。
然而,在工作GAE时,你会发现自己很多时候会按惯例做事。
EDIT阻止多个访问令牌引用同一用户:
您可以通过User.usertwitteroauth_set
属性访问引用访问令牌作为查询。如果需要更具描述性的名称,请在设置ReferenceProperty时指定参数collection_name
。比如说你想在添加一个新引用令牌之前删除任何引用访问令牌,你可以这样收集逻辑:
class User(db.Model):
def set_access_token(self, access_token):
db.delete(self.twitter_access_tokens) # Think this should work, otherwise iterate over the query.
new_access_token.user = self
new_access_token.put()
class UserTwitterOauth(db.Model):
user = db.ReferenceProperty(User, collection_name = 'twitter_access_tokens')