Google App Engine получает PolyModel в качестве дочернего класса

Когда я запускаю Google App Engine Likeo:

 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. 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 ответа

Решение

Я не могу воспроизвести вашу проблему - действительно, ваш код просто умирает с ошибкой импорта (PolyModel не в модуле db) на моем GAE (версия 1.2.5). После того, как я исправил все, чтобы код работал...:

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

... Я вижу "Спаун говорит привет", как и ожидалось. Какой релиз App Engine у ​​вас есть? Что произойдет, если вы будете использовать именно тот код, который я даю?

Вы сделали "Father.get...", поэтому вы создали объект из класса Отца. Так почему бы не сказать "Отец говорит привет".

Если у вашего отцовского класса были фамилия и имя, а у вашего сына - отчество, вы не получите отчество, если не получите специальную запись "Сын".

Если вы хотите сделать запрос полиморфного типа, вот один из способов сделать это. Я знаю, что это работает с атрибутами, но не пробовал это с методами.

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

Нил Уолтерс

Другие вопросы по тегам