bgenchel
bgenchel

Reputation: 4049

NDB PolyModel Problems

I'm working on a google app engine app in which we use polymodel to express a subset of the entities. I'm having problems using it in the way that the docs claim it works though.

My first problem is that I noticed that a call on an 'inherited' method on an entity that is the type of the subclass is instead calling the parent polymodel's version of that method, which is just a 'pass'. Thus the method returns None and messes everything up.

EDIT: It appears that this is the case not just for the method call, but for all of it's properties. When I try to log some specific info that the subclass has but the parent doesn't, it throws an error saying that it can't find that info.

e.g.

class Parent(polymodel.PolyModel):
    def someMethod(self, params):
        pass

class Child(Parent):
    def someMethod(self, params):
        {{logic}}
        return something

The second problem I found, as a result of trying to solve the first, is that the 'class_name()' method, which is reported to exist here: https://cloud.google.com/appengine/articles/polymodel, does not seem to work.

When I call it, I get a server error that ends with AttributeError: 'Parent' object has no attribute 'class_name'. My class is not actually called 'Parent', I just wanted to keep consistent with my earlier example.

It's all very frustrating, and I don't really know how to proceed. Any help appreciated!

EDIT

Here is perhaps a more detailed description of what is happening:

I have defined a polymodel class that I do not want to instantiate; I only want it to serve as a template class. It has template methods that I want to be defined in all of it's children; all are pass. It lives in my main models file

class Template(polymodel.PolyModel):
    def method_one(self):
        logging.error("ENTERED TEMPLATE METHOD, THIS SHOULD NOT HAPPEN")
        pass

    def method_two(self):
        logging.error("ENTERED TEMPLATE METHOD, THIS SHOULD NOT HAPPEN")
        pass

In another file, lets call it template_extension_models.py, in the same directory as the main models file, I've defined an extension of the Template model that populates it's methods with real logic.

class TemplateExtension(Template):
    def method_one(self):
       """
       some logic specific to this class, actually
       takes inputs and returns something
       """

    def method_two(self):
       """
       some logic specific to this class, actually
       takes inputs and returns something
       """

Back in the main models file, we have certain classes that have ndb.KeyProperties that point to 'Template'. The hope/assumption is that this will act like other inheritance models, and so when we pull from the datastore an entity of type/subtype of 'Template', we can call it's method_one() and method_two() and the code for that specific instance's method_one and method_two will run. i.e.

 class OtherThing(ndb.Model):
     template = ndb.KeyProperty(kind=Template)

     def get_template_and_call_method(self):
         template = self.template.get()
         res = template.method_one()
         do_something_with(res)

Here is where my problem is happening. We never actually use Template; for each instance of 'OtherThing', we are actually assigning an instance of TemplateExtension. Yet, randomly, not every time, after pulling out the template in OtherThing's method (a generalization of several places in my actual code), I see the method of the Template parent class being called instead of the TemplateExtension class, which causes a ton of errors. Since this doesn't happen every time, I'm not sure where to begin looking for the problem.

Upvotes: 0

Views: 214

Answers (1)

Brent Washburne
Brent Washburne

Reputation: 13138

It's called _class_name() with a leading underscore.

https://cloud.google.com/appengine/docs/python/ndb/polymodelclass

Upvotes: 2

Related Questions