La clase PolyModel
permite que una aplicación defina modelos que admitan consultas polimórficas de una forma más flexible que la clase Model
estándar.
Una consulta generada a partir de una clase derivada de PolyModel
puede tener resultados que sean instancias de la clase o de cualquiera de sus subclases.
Se define en google.appengine.ext.ndb.polymodel
. En el siguiente ejemplo se muestra la flexibilidad que ofrece la clase 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()
devuelve Person
y Company
instancias;
si Contact
se deriva de Model
en lugar de
PolyModel
, cada clase tendría un kind
diferente
y Contact.query()
no devolvería instancias de
subclases adecuadas de Contact
.
Si solo quieres obtener instancias de Person
,
usa Person.query()
. También puedes usar
Contact.query(Contact.class_ == 'Person')
.
Además de los métodos de Model habituales, PolyModel tiene algunos métodos de clase interesantes:
_get_kind()
: el nombre de la clase raíz (por ejemplo,Person._get_kind() == 'Contact'
). La clase raíz, Contact en este ejemplo, puede anular este método para usar otro nombre como el tipo usado en el almacén de datos (para toda la jerarquía que tiene su raíz aquí)._class_name()
: el nombre de la clase actual (por ejemplo,Person._class_name() == 'Person'
). Una clase hoja, como Person en nuestro ejemplo, puede anular este método para usar un nombre diferente como nombre de clase y en la clave de clase. Una clase que no sea hoja también puede anular este método, pero ten cuidado: sus subclases también deben anularlo, ya que, de lo contrario, todas usarán el mismo nombre de clase y te confundirás._class_key()
: una lista de nombres de clase que indica la jerarquía. Por ejemplo,Person._class_key() == ['Contact', 'Person']
. En el caso de las jerarquías más profundas, se incluirán todas las bases entrePolyModel
y la clase actual, incluida esta última, pero excluyendo PolyModel. Es el mismo valor que el de la propiedadclass_
. Su nombre de almacén de datos es "class".
Como el nombre de la clase se usa en la propiedad class_
y esta propiedad se usa para distinguir entre las subclases, los nombres de las clases (tal como los devuelve _class_name()
) deben ser únicos entre esas subclases.