在重复的StructuredProperty中,自定义属性未正确保存为Expando模型 [英] Custom properties not saved correctly for Expando models in repeated StructuredProperty
问题描述
我试图在另一个模型中使用 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 $的 我做错了什么? 谢谢。 这是ndb如何存储 例如,考虑实体: 这实际上会存储在一个看起来像这样的实体中: Account
实例中(在索引0处)!
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')))
{
,ndb不知道它应该使用
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 None填充
为facebook账户。当ndb重新填充您的实体时,它会为它所看到的第一个帐户填写 access_token_secret
字段 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屋!