Google App Engine 获取子类的 PolyModel

0 投票
2 回答
779 浏览
提问于 2025-04-15 14:35

当我这样运行 Google App Engine 时:

 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"

例如,我运行:

 s = Son()
 s.put()

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

 son_from_father.hello()

这段代码输出了“父亲说你好”。我本来期待它输出“儿子说你好”。有没有人知道怎么才能让它按预期工作呢?

编辑:

问题的根本原因是,我把 Spawn 对象保存成了 Father 对象。虽然 Father 对象在我的应用中属性更少,但 GAE 还是能接受这种做法。GAE 没有报错,因为我(默默地)把不在 Model.properties() 中的值从要保存的数据中去掉了。

我已经修正了错误的类型保存,并添加了一个检查,确保不会保存多余的值(这个检查的位置正好有个 TODO 注释提醒我)。我在保存数据时进行的检查基本上是:

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!")

这里的帖子对我很有帮助 - 谢谢大家。现在 GAE 按照预期工作了,因为我按照指示使用它。 :)

2 个回答

-1

你用了“Father.get...”这个方法,所以你是从Father类创建了一个对象。那为什么不说“Father说你好”呢?

如果你的Father类有姓和名,而你的Son类有中间名的话,除非你特别去获取“Son”的记录,否则你是拿不到中间名的。

如果你想进行多态查询,这里有一种方法可以做到。我知道它在属性上是有效的,但还没尝试过在方法上使用。

 fatherList = Father.all().fetch(1000) 
 counter = 0 
 #I'm using lower case father for object and upper case Father for your class...
 for father in fatherList:
     counter += 1 
     if isinstance(father,Son):
        self.response.out.write("display a Son field or do a Son method") 
     if isinstance(father,Daughter):
        self.response.out.write("display a Daughter field or do a Daughter method")

尼尔·沃尔特斯

1

我无法重现你遇到的问题——实际上,在我的GAE(版本1.2.5)上,你的代码直接因为导入错误而崩溃(PolyModel在模块db中找不到)。一旦我修复了一些问题,让代码可以运行...:

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()

...我看到“Spawn says hi”,这正是我预期的结果。你使用的App Engine版本是什么?如果你完全使用我给的代码,会发生什么呢?

撰写回答