【问题标题】:New entity in repeated StructuredProperty stored as a _BaseValue重复 StructuredProperty 中的新实体存储为 _BaseValue
【发布时间】:2014-03-04 22:52:29
【问题描述】:

我有一个 HUser 模型(源自 Google 的 User 类),它又包含 0 到 n 个社交帐户实例。这些帐户可以是对 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' 对象没有属性 '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))

感谢您的帮助!

【问题讨论】:

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


    【解决方案1】:

    您如何访问重复的属性? 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
    

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

    【讨论】:

    • 我不记得我是否在做这样的事情,但我可能曾经做过。同时,由于另一个问题(你也在 SO 上帮助我解决了这个问题),我不得不改变我的设计。这些更改显着减少了我的代码中 put() 的数量,尤其是在管理 Twitter 帐户时。在发布我的问题之前,我发现了您所指的错误,但我不太了解它的含义和含义。你的回答让它更清楚一点。所以,你总结一下,为了以后避免这个问题,我需要避免处理ndb实体的本地副本,对吗?
    • 我认为关键是您应该避免处理 ndb properties 的本地副本。只要您直接从 ndb 实体访问该属性,它就会做正确的事情。
    • @PatrickCostello,但是如果您的实体有一个您想要枚举以进行操作的键列表怎么办?例如。对于 ndb_file.jobs 中的 job_key:job = job_key.get() ... 这适用于我的代码中的其他地方,但不适用于这种特殊情况。
    • 只要你总是写 for prop in mymodel.props: 这应该可以工作,因为你是从 ndb 对象访问列表。你不能做的是:props = mymodel.props 然后for prop in props
    猜你喜欢
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多