4

I have some models that share a common set of properties, which I have defined in a base model class from which other models inherit:

class BaseUser(ndb.Model):
    name = ndb.StringProperty()

class DerivedUserA(BaseUser):
    # some additional properties...

class DerivedUserB(BaseUser):
    # some additional properties...

In some other model, I need a reference to any BaseUser-derived model:

class MainModel(ndb.Model):
    user = ndb.KeyProperty(kind = BaseUser)

However, When I try to set a DerivedUserA entity key to the MainModel.user property, GAE raises a BadValueError stating that it is expecting a key with kind BaseUser but was given a DerivedUserA.

If I remove the kind argument from my MainModel, it works:

class MainModel(ndb.Model):
    user = ndb.KeyProperty()

I could live with that, but I'd rather have a check in place to make sure that I am not trying to save any kind of entity in the MainModel.user property. Is there a way to do that?

Pascal Bourque
  • 5,101
  • 2
  • 28
  • 45

2 Answers2

3

Use PolyModel for datastore inheritance -> https://developers.google.com/appengine/docs/python/ndb/polymodelclass

Gwyn Howell
  • 5,365
  • 2
  • 31
  • 48
  • Wow, even after spending the last 2 days immersed in ndb's documentation, this class somehow stayed under the radar. Thanks a lot! – Pascal Bourque Aug 15 '12 at 20:18
3

The reason this doesn't work is that the kind parameter to KeyProperty() gets translated to a string immediately.
Since it's only a validation feature, we could consider fixing this though.
If you like this idea, you could file a feature request in the tracker: http://code.google.com/p/appengine-ndb-experiment/issues/list -- this would be less heavyweight than PolyModel (although it seems PolyModel might be what you're looking for anyway).

systempuntoout
  • 71,966
  • 47
  • 171
  • 241
Guido van Rossum
  • 16,690
  • 3
  • 46
  • 49
  • Thanks! Indeed, PolyModel is what I need because it solves another problem I had with my initial model inheritance, which was that I was not able to perform a query among all BaseUser-derived entities (since they were stored in different datastore tables). I don't think I'd ask you to fix this in KeyProperty, as it seems like PolyModel is really the way to do model inheritance properly. – Pascal Bourque Aug 16 '12 at 12:51