3

假设您有一个想要存储在数据存储中的“用户”记录的概念。

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 中为用户放置一个 ReferenceProperty,但这实际上是一对多的,因为没有什么可以阻止每个用户拥有多个 UserTwitterOauth 对象。您希望最多有一个与任何用户相关的 UserTwitterOauth。您如何将这些模型一对一地关联起来?

4

2 回答 2

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,除非你对你的导入非常小心,否则当你打算引用另一个时,你最终可能会引用一个。

于 2011-06-08T00:31:40.907 回答
0

在我看来,从 twitter 访问令牌到用户的引用属性是迄今为止最容易维护的。确实,用户可以被许多访问令牌引用。

然而,在使用 GAE 时,您会发现自己很多时候都在按照惯例做事。

编辑防止引用同一用户的多个访问令牌:

User.usertwitteroauth_set您可以通过属性访问引用访问令牌作为查询。如果您想要一个更具描述性的名称,请collection_name在设置 ReferenceProperty 时指定参数。例如,您想在添加新的访问令牌之前删除任何引用访问令牌,您可以这样收集该逻辑:

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')
于 2011-06-07T16:39:21.390 回答