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

Rom*_*ain 2 python google-app-engine app-engine-ndb google-cloud-datastore

我有一个HUser模型(源自谷歌的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)
Run Code Online (Sandbox Code Playgroud)

如果我只向我的用户添加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))
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助!

Pat*_*llo 6

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

myUser = HUser(...)
accounts = myUser.accounts
myUser.put()
accounts[0] # This is a _BaseValue(Account)
myUser.accounts[0] # This is an Account
Run Code Online (Sandbox Code Playgroud)

这是ndb问题跟踪器上的一个漏洞.

  • 我认为关键是您应该避免使用 ndb **properties** 的本地副本。只要您直接从 ndb 实体访问该属性,它就会做正确的事情。 (2认同)