重复的StructuredProperty中的新实体存储为_BaseValue

时间:2014-03-04 22:52:29

标签: python google-app-engine google-cloud-datastore app-engine-ndb

我有一个HUser模型(源自Google的User类),后者又包含0到n个社交帐户实例。这些帐户可以引用Facebook,Twitter或LinkedIn帐户。我构建了Account模型,并在StructuredProperty模型中使用User定义了repeated=True,如下所示:

class Account(ndb.Expando):
    account_type = ndb.StringProperty(required=True, choices=['fb', 'tw', 'li'])
    account_id = ndb.StringProperty()
    access_token = ndb.StringProperty()
    ...

class HUser(User):
    email = ndb.StringProperty(required=True, validator=validate_email)
    created = ndb.DateTimeProperty(auto_now_add=True)
    accounts = ndb.StructuredProperty(Account, repeated=True)

如果我只向用户添加Facebook或LinkedIn帐户,一切都按预期工作。但奇怪的是,每当我添加Twitter帐户时,我添加到同一用户的所有后续帐户都将存储为_BaseValue(Account()),而不是Account()。因此,在我尝试提取帐户的页面中,我通常会遇到以下错误:

  

AttributeError:'_ BaseWalue'对象没有属性'account_type'

我已经读过这些_BaseValue转换是Google的ndb源代码中的一个错误,但我怎么能摆脱它呢?目前我正在使用这种糟糕的解决方法来绕过异常:

if type(account) == _BaseValue:
    account = account.b_val
    logging.warn("WARN: %s account %s was of type _BaseValue..." % (account.account_type, account.account_id))

感谢您的帮助!

1 个答案:

答案 0 :(得分:6)

您如何访问重复的财产? ndb模型将属性存储为_BaseValue并将“无缝地”(遗憾的是并非总是如此)转换为您的类型(在ndb中称为UserValue)。因此,您必须注意如何在模型之外存储属性。考虑一下:

myUser = HUser(...)
accounts = myUser.accounts
myUser.put()
accounts[0] # This is a _BaseValue(Account)
myUser.accounts[0] # This is an Account

这是ndb问题跟踪器上的open bug