Classe PolyModel

La classe PolyModel consente a un'applicazione di definire modelli che supportano le query polimorfiche, in modo più flessibile rispetto alla classe Model standard. Una query prodotta da una classe derivata PolyModel può avere risultati che sono istanze della classe o di una qualsiasi delle sue sottoclassi.

È definito in google.appengine.ext.ndb.polymodel. L'esempio seguente mostra la flessibilità offerta dalla 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() restituisce istanze Person e Company; se Contact deriva da Model anziché da PolyModel, ogni classe avrà un elemento kind diverso e Contact.query() non restituirà istanze delle sottoclassi corrette di Contact.

Se vuoi recuperare solo Person istanze, utilizza Person.query(). Puoi anche utilizzare Contact.query(Contact.class_ == 'Person').

Oltre ai normali metodi Model, PolyModel offre alcuni metodi interessanti delle classi:

  • _get_kind(): il nome della classe radice, ad esempio Person._get_kind() == 'Contact'. La classe radice, Contact in questo esempio, potrebbe sostituire questo metodo in modo da utilizzare un nome diverso rispetto a quello utilizzato nel datastore (per l'intera gerarchia radice qui).
  • _class_name(): il nome della classe corrente, ad esempio Person._class_name() == 'Person'. Una classe foglia, Person nel nostro esempio, può sostituire questo metodo in modo da utilizzare un nome diverso come nome della classe e nella chiave della classe. Anche una classe non foglia può eseguire l'override di questo metodo, ma attenzione: anche le sue sottoclassi dovrebbero sovrascriverlo, altrimenti utilizzeranno tutte lo stesso nome di classe e presto ti sentirai molto confuso.
  • _class_key(): un elenco di nomi di classi che forniscono la gerarchia. Ad esempio, Person._class_key() == ['Contact', 'Person']. Per gerarchie più profonde, questo includerà tutte le basi tra PolyModel e la classe corrente, inclusa la seconda, ma escludendo PolyModel stesso. Corrisponde al valore della proprietà class_. Il nome del datastore è "class".

Poiché il nome della classe viene utilizzato nella proprietà class_ e questa viene utilizzata per distinguere tra le sottoclassi, i nomi delle classi (come restituiti da _class_name()) devono essere univoci tra queste sottoclassi.