在重复的StructuredProperty中,自定义属性未正确保存为Expando模型 [英] Custom properties not saved correctly for Expando models in repeated StructuredProperty

查看:108
本文介绍了在重复的StructuredProperty中,自定义属性未正确保存为Expando模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在另一个模型中使用 Expando 模型作为重复的 StructuredProperty 。也就是说,我想向我的 User 模型中添加一个不定数量的 Accounts 。由于帐户可以根据其类型具有不同的属性(帐户是对社交网络帐户的引用,例如Twitter要求比Facebook更多的OAuth流程信息),我将账户模型设计为 Expando 。我在模型定义中添加了所有基本信息,但我打算为特定社交网络添加自定义属性(例如,Twitter的特定 access_token_secret 属性)。



1 /您可以通过重复 StructuredProperty Expando >)工作?

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

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



<2>现在我面临的问题是:当我向我的 HUser 实例添加一个Facebook帐户时,everythi ng正常工作;然而,当我将Twitter帐户添加到同一个实例并添加一个未在模型中声明的新属性时,问题就会增加:

 用于huser.accounts帐户:
如果account.state ==state_we_re_looking_for和account.account_type =='tw':
#我们找到适当的Twitter帐户参考
帐户.access_token_secret =...#存储从Twitter API获取的访问令牌密码
huser.put()#保存到数据存储区
break

这个操作应该保存我的<$ c $的账户实例中的访问令牌密码c> User ,但实际上它将它保存在 Facebook Account 实例中(在索引0处)!

我做错了什么?

谢谢。

解决方案

这是ndb如何存储 StructuredProperty 的一个基本问题。数据存储目前还没有办法存储这个,所以ndb基本上爆炸你的属性。



例如,考虑实体:

  HUser(email='test@example.com'。
accounts =(Account(type ='fb',
account_id ='1' ,
state ='1',
access_token ='1'),
Account(type ='tw',
account_id ='2',
state = '2',
access_token ='2',
access_token_secret ='2')))

这实际上会存储在一个看起来像这样的实体中:

  {
email:'test @ example.com',
accounts.type:['fb','tw'],
accounts.account_id:['1','2'],
accounts.state: ['1','2'],
accounts.access_token:['1','2'],
因为您使用的是<$ code> ndb.Expando
,ndb不知道它应该使用 None填充 access_token_secret 字段为facebook账户。当ndb重新填充您的实体时,它会为它所看到的第一个帐户填写 access_token_secret ,这是Facebook帐户。



重构数据听起来像是正确的方式,但是您可能希望使您的HUser成为 Account的一个祖先,该 HUser ,以便您使用强一致性查询用户的帐户


I am trying to use an Expando model as a repeated StructuredProperty in another model. Namely, I would like to add an indefinite number of Accounts to my User model. As Accounts can have different properties depending on their types (Accounts are references to social network accounts, and for example Twitter requires more information than Facebook for its OAuth process), I have designed my Account model as an Expando. I've added all basic information in the model definition, but I plan to add custom properties for specific social networks (e.g., a specific access_token_secret property for Twitter).

1/ Can you confirm the following design (Expando in repeated StructuredProperty) should work?

class Account(ndb.Expando):
    account_type = ndb.StringProperty(required=True, choices=['fb', 'tw', 'li'])
    account_id = ndb.StringProperty()
    state = 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)

2/ Now the problem I am facing is: when I add a Facebook account to my HUser instance, everything works fine ; however the problem rises when I append a Twitter account to that same instance, and add a new property not declared in the model, like that:

for account in huser.accounts:
    if account.state == "state_we_re_looking_for" and account.account_type == 'tw':
        # we found the appropriate Twitter account reference
        account.access_token_secret = "..." # store the access token secret fetched from Twitter API
        huser.put() # save to the Datastore
        break

This operation is supposed to save the access token secret in the Twitter Account instance of my User, but in fact it saves it in the Facebook Account instance (at index 0)!

What am I doing wrong?

Thanks.

解决方案

This is a fundamental problem with how ndb stores the StructuredProperty. Datastore does not currently have a way to store this, so ndb basically explodes your properties.

For example, consider the entity:

HUser(email='test@example.com'.
      accounts=(Account(type='fb',
                        account_id='1',
                        state='1',
                        access_token='1'),
                Account(type='tw',
                        account_id='2',
                        state='2',
                        access_token='2',
                        access_token_secret='2')))

This will actually get stored in an entity that looks like:

{
 email : 'test@example.com',
 accounts.type : ['fb', 'tw'],
 accounts.account_id : ['1', '2'],
 accounts.state : ['1', '2'],
 accounts.access_token : ['1', '2'],
 accounts.access_token_secret : ['2']
}

Because you are using an ndb.Expando, ndb doesn't know that it should populate the access_token_secret field with a None for the facebook account. When ndb repopulates your entities, it will fill in the access_token_secret for the first account it sees, which is the facebook account.

Restructuring your data sounds like the right way to go about this, but you may want to make your HUser an ancestor of the Account for that HUser so that you query for a user's accounts using strong consistency.

这篇关于在重复的StructuredProperty中,自定义属性未正确保存为Expando模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆