pythongoogle-app-enginegoogle-cloud-datastoreendpoints-proto-datastore

Referring a single Google datastore kind multiple times in another kind with ndb


I have the below 2 ndb models

from endpoints_proto_datastore.ndb import EndpointsModel

class Foo(EndpointsModel):
    attr1 = ndb.StringProperty(required=True)

class Bar(EndpointsModel):
    attr1 = ndb.KeyProperty('Foo', required=True)
    attr2 = ndb.KeyProperty('Foo', required=True)

As you see Bar has a couple of references to Foo.

Now when I assign values to each of the references, the second one replaces the first and only it gets stored to the db and the funniest part is that when looked up with the dev_appserver datastore viewer, the property is under the name 'Foo', not under the second property's name, that replaced the first one.

After I insert this is what I expect

Bar(key=Key('Bar', xxxxxxxxxxxxxxxx), attr1=Key('Foo', xxxxxxxxxxxxxxxx), attr2=Key('Foo', xxxxxxxxxxxxxxxx)

but I only get

Bar(key=Key('Bar', xxxxxxxxxxxxxxxxxx), attr2=Key('Foo', xxxxxxxxxxxxxxxx))

And in the datastore viewer,

Entity Kind Bar

Entity Key  xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

ID          xxxxxxxxxxxxxxxx


Foo (Key)   xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Foo: id=xxxxxxxxxxxxxxxx

Solution

  • The first argument to KeyProperty is the name for the property (if you want to have the name be different to the class-property), so using the same name twice will produce the behaviour you're seeing.

    You should use a named argument instead to specify the kind:

    ndb.KeyProperty(kind='Foo', required=True)