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")
Нил Уолтерс