Search code examples
pythongoogle-app-enginereferenceproperty

Get a datastore object by getattr without knowing its class


I want to get a entity through a ReferencePropery in this way.

getattr(model, refrence)

where model is a db.Model and reference is db.ReferenceProperty. But I get a KindError, which I can avoid by adding import of following sort.

from foomodule import ReferedKind

Where ReferedKind is the class of the entity I want to get by above getattr.

But my problem is in my case because of the nature of the function I want to call this in, the model can belong to any Model class of mine. So I don't know what the ReferedKind will be.

How can I call getattr and get the referred entity without importing every possible model class?

Is there a way I can know the class of a entity referred by a ReferanceProperty in advance so I can dynamically import it?

Aditional info

I am writing a function that would return a json serializable python dict. Because in some cases dictionary returned by db.to_dict() is not json serializable. So the function doesn't know in advance what kind of a model it will have to put into a dict.


Solution

  • Normally you need to import all potential models that you could retrieve before doing anything.

    Your making things hard for yourself.

    The only way you do it would be to work at a lower level than db.Model or ndb.Model to fetch the raw data then examine it then you will still need to import the model before dereferencing a referenceproperty or fetching a key.

    If you decide to do this ndm will be easier as it doesn't have a reference property, but a KeyProperty, you can use getattr, check if you have a key, then fetch the object referred to be the key.

    If you want to stick with db. it will be messy because you need to use get_value_for_datastore

    Which would involve,

    getting the class of the entity, getting the property of the class and then calling get_value_for_datastore passing in the instance then assuming you have imported the you can get the key.

    so if you have an instance from the datastore called foo you would

    prop = getattr(foo.__class__,"the_property_name")
    obj_key = prop.get_value_for_datastore(foo)
    

    Then you will need to get the kind from the key, then work out how to import the model for that kind, before you get() the key, other wise you will still get the KindError

    I am not sure all the effort is worth it, you will find it easier to just import the models. You ultimately need to import any model before you use it. The only thing you are might be gaining is a lazy import potentially saving some startup time.