A classe PolyModel
possibilita que um aplicativo defina modelos compatíveis com consultas polimórficas com mais flexibilidade que a classe Model
padrão.
Uma consulta produzida por uma classe derivada de PolyModel
pode ter como resultados instâncias da classe ou de qualquer das subclasses dela.
Está definida em google.appengine.ext.ndb.polymodel
. O exemplo a seguir mostra a flexibilidade da classe PolyModel.
from google.appengine.ext import ndb from google.appengine.ext.ndb import polymodel class Contact(polymodel.PolyModel): phone_number = ndb.PhoneNumberProperty() address = ndb.PostalAddressProperty() class Person(Contact): first_name = ndb.StringProperty() last_name = ndb.StringProperty() mobile_number = ndb.PhoneNumberProperty() class Company(Contact): name = ndb.StringProperty() fax_number = ndb.PhoneNumberProperty() p = Person(phone_number='1-206-555-9234', address='123 First Ave., Seattle, WA, 98101', first_name='Alfred', last_name='Smith', mobile_number='1-206-555-0117') p.put() c = Company(phone_number='1-503-555-9123', address='P.O. Box 98765, Salem, OR, 97301', name='Data Solutions, LLC', fax_number='1-503-555-6622') c.put() for contact in Contact.query(): print 'Phone: %s\nAddress: %s\n\n' % (contact.phone_number, contact.address)
Contact.query()
retorna instâncias Person
e Company
.
Se Contact
fosse derivado de Model
em vez de
PolyModel
, cada classe teria um kind
diferente e Contact.query()
retornaria instâncias de subclasses apropriadas de Contact
.
Caso você queira recuperar apenas instâncias Person
,
use Person.query()
. Também é possível usar o Contact.query(Contact.class_ == 'Person')
.
Além dos métodos regulares Model, PolyModel tem alguns métodos de classe interessantes:
_get_kind()
: o nome da classe raiz. Por exemplo,Person._get_kind() == 'Contact'
. A classe raiz, Contact neste exemplo, pode modificar esse método para usar um nome diferente como o tipo usado no armazenamento de dados (para toda a hierarquia enraizada aqui)._class_name()
: o nome da classe atual. Por exemplo,Person._class_name() == 'Person'
. Uma classe folha, Person neste exemplo, pode modificar esse método para usar um nome diferente como o nome da classe e na chave da classe. Uma classe não folha também pode modificar este método, mas cuidado: as subclasses também precisam substituí-la, ou elas usarão o mesmo nome de classe e em breve você ficará muito confuso._class_key()
: uma lista de nomes de classe que dão a hierarquia. Por exemplo,Person._class_key() == ['Contact', 'Person']
. Para hierarquias mais profundas, isso incluirá todas as bases entrePolyModel
e a classe atual, inclusive esta última, mas exceto a própria PolyModel. Este é o mesmo valor da propriedadeclass_
. O nome do armazenamento de dados é "class".
Como o nome da classe é usado na propriedade class_
e essa propriedade é usada para distinguir entre as subclasses, os nomes das classes (conforme retornado por _class_name()
) precisam ser exclusivos entre essas subclasses.