Search code examples
pythongoogle-app-enginepolymodel

Google App Engine get PolyModel as child class


When I run Google App Engine likeso:

 from google.appengine.ext import db
 from google.appengine.ext.db import polymodel

 class Father(polymodel.PolyModel):
      def hello(self):
          print "Father says hi"

 class Son(Father):
      def hello(self):
          print "Spawn says hi"

When I run, e.g.

 s = Son()
 s.put()

 son_from_father = Father.get_by_id(s.key().id())

 son_from_father.hello()

This prints "Father says hi". I would expect this to print "Son says hi". Does anyone know how to make this do what's expected, here?

EDIT:

The problem was, ultimately, that I was saving Spawn objects as Father objects. GAE was happy to do even though the Father objects (in my application) have fewer properties. GAE didn't complain because I (silently) removed any values not in Model.properties() from the data being saved.

I've fixed the improper type saving and added a check for extra values not being saved (which was helpfully a TODO comment right where that check should happen). The check I do for data when saving is basically:

def save_obj(obj, data, Model):
   for prop in Model.properties(): # checks/other things happen in this loop
      setattr(obj, prop, data.get(prop))

   extra_data = set(data).difference(Model.properties())
   if extra_data:
      logging.debug("Extra data!")

The posts here were helpful - thank you. GAE is working as expected, now that I'm using it as directed. :)


Solution

  • I can't reproduce your problem -- indeed, your code just dies with an import error (PolyModel is not in module db) on my GAE (version 1.2.5). Once I've fixed things enough to let the code run...:

    import wsgiref.handlers
    from google.appengine.ext import webapp
    from google.appengine.ext.db import polymodel
    
    class Father(polymodel.PolyModel):
        def hello(self):
            return "Father says hi"
    
    class Son(Father):
        def hello(self):
            return "Spawn says hi"
    
    class MainHandler(webapp.RequestHandler):
    
      def get(self):
        s = Son()
        s.put()
        son_from_father = Father.get_by_id(s.key().id())
        x = son_from_father.hello()
        self.response.out.write(x)
    
    def main():
      application = webapp.WSGIApplication([('/', MainHandler)],
                                           debug=True)
      wsgiref.handlers.CGIHandler().run(application)
    
    
    if __name__ == '__main__':
      main()
    

    ...I see "Spawn says hi" as expected. What App Engine release do you have? What happen if you use exactly the code I'm giving?