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

2 投票
1 回答
802 浏览
提问于 2025-04-17 20:51

我有一个叫做 HUser 的模型,它是从谷歌的 User 类派生出来的。这个模型里面可以包含0到多个社交账号,这些账号可以是Facebook、Twitter或者LinkedIn的账号。我还建立了一个 Account 模型,并在我的 User 模型中定义了一个 StructuredProperty,并设置了 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: '_BaseValue' object has no attribute 'account_type'

我听说这些 _BaseValue 转换是谷歌的ndb源代码中的一个bug,但我该如何解决这个问题呢?目前我正在使用一个很糟糕的变通方法来绕过这些异常:

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 个回答

7

你是怎么访问你重复的属性的?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的公开错误,可以在ndb的问题追踪器上找到。

撰写回答