La classe PolyModel

Nota: gli sviluppatori che creano nuove applicazioni sono vivamente incoraggiati a utilizzare la libreria client NDB, che offre diversi vantaggi rispetto a questa libreria client, ad esempio la memorizzazione nella cache automatica delle entità tramite l'API Memcache. Se al momento utilizzi la libreria client DB precedente, leggi la guida alla migrazione da DB a NDB

La classe PolyModel è la superclasse per le definizioni del modello dei dati che possono essere a loro volta superclassi per altre definizioni del modello dei dati. Una query prodotta da un modello PolyModel può avere risultati che sono istanze del modello o di uno dei suoi sottomodelli.

PolyModel è fornito dal modulo google.appengine.ext.db.polymodel.

PolyModel è una sottoclasse di Model e ne eredita i metodi di classe e di istanza. La classe PolyModel sostituisce diversi metodi di Model, ma non introduce nuovi elementi di interfaccia.

Introduzione

Spesso è utile definire i modelli di dati come una gerarchia di classificazione, in modo simile a come un database di oggetti può definire una classe di oggetti come sottoclasse di un'altra. Un database di questo tipo può eseguire query sugli oggetti della classe principale e includere gli oggetti della sottoclasse nei risultati. Il datastore di App Engine non supporta questo tipo di query in modo nativo, ma puoi implementarlo utilizzando un meccanismo incluso nell'SDK Python, la classe PolyModel.

Una classe di modelli derivata da PolyModel può essere la classe di base per altre classi di modelli. Le query create per queste classi utilizzando i metodi all() e gql() sanno includere istanze di sottoclassi nei risultati.

Le sottoclassi possono definire nuove proprietà non presenti nelle classi principali. Tuttavia, i sottoclassi non possono sostituire le definizioni delle proprietà delle classi principali. In questo modo si verifica un errore DuplicateProperty.

Come riferimento, ecco un semplice esempio tratto da Entità e modelli. Tieni presente che la classe PolyModel è fornita dal pacchetto google.appengine.ext.db.polymodel.

from google.appengine.ext import db
from google.appengine.ext.db import polymodel

class Contact(polymodel.PolyModel):
    phone_number = db.PhoneNumberProperty()
    address = db.PostalAddressProperty()

class Person(Contact):
    first_name = db.StringProperty()
    last_name = db.StringProperty()
    mobile_number = db.PhoneNumberProperty()

class Company(Contact):
    name = db.StringProperty()
    fax_number = db.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.all():
  # Returns both p and c.
  # ...

for person in Person.all():
  # Returns only p.
  # ...

Il polimorfismo non è una funzionalità nativa del datastore. Il polimorfismo viene invece implementato nella classe PolyModel stessa. Tutte le entità create dai sottoclassi PolyModel vengono archiviate nel datastore con lo stesso tipo, ovvero il nome della classe principale (ad es. Animal). Ogni oggetto memorizza la propria gerarchia di classi come proprietà multivalore dell'entità denominata 'class'. Quando l'app crea una query utilizzando il metodo all() o gql() di una classe PolyModel, la query include un filtro sulla proprietà 'class' che limita i risultati alle entità create dalla classe o da qualsiasi sottoclasse.

Poiché PolyModel utilizza una proprietà dell'entità per memorizzare le informazioni sulla classe, gli indici per le query polimorfiche devono essere compatibili con la proprietà 'class'. Il filtro implicito è un filtro di uguaglianza e può essere combinato con altri filtri di uguaglianza e di disuguaglianza in altre proprietà.

Nota:PolyModel utilizza solo i nomi delle classi nella proprietà 'class', non i percorsi completi. È possibile creare gerarchie di classi con più nodi dello stesso nome, ad esempio AB e ACB. Una query per uno restituirà le entità di entrambi. Analogamente, le query per ABC e ACB sono funzionalmente identiche. È meglio evitare di creare una singola gerarchia di classi con più nodi con lo stesso nome.

PolyModel non supporta l'override delle definizioni del modello di proprietà nei sottoclassi. Se una sottoclasse tenta di ridefinire una proprietà definita in una superclasse, la definizione della classe genera un DuplicatePropertyError.

PolyModel supporta l'eredità multipla, inclusa l'eredità da più classi che condividono un superclasse ("eredità a diamante"). Una classe non può ereditare da due classi che definiscono ciascuna una definizione del modello di proprietà per la stessa proprietà (verrebbe generato un errore DuplicatePropertyError). Tuttavia, una classe può ereditare da due classi che ereditano la stessa definizione del modello di proprietà dalla stessa superclasse.

PolyModel non supporta le proprietà dinamiche, come fa Expando. Non esiste un equivalente di PolyModel per Expando.

Costruttore

Il costruttore della classe PolyModel è definito come segue:

class PolyModel(parent=None, key_name=None, **kwds)

Una classe modello che può essere una superclasse di altre classi modello e le cui query possono includere istanze di sottoclassi come risultati. Come Model, la classe PolyModel deve essere sottoclassificata per definire il tipo di entità di dati.

PolyModel è una sottoclasse di Model ed eredita o sostituisce i relativi metodi.

Argomenti

parent
L'istanza Model o Key per l'entità principale della nuova entità.
key_name

Il nome della nuova entità. Il nome diventa parte della chiave primaria. Se None, per la chiave viene utilizzato un ID generato dal sistema.

Il valore di key_name non deve iniziare con un numero e non deve essere del tipo __*__. Se l'applicazione utilizza i dati inviati dagli utenti come nomi delle chiavi delle entità del datastore (ad esempio un indirizzo email), deve prima eseguire la sanitizzazione del valore, ad esempio anteponendo una stringa nota come "key:", per soddisfare questi requisiti.

Un key_name viene archiviato come stringa Unicode, con i valori str convertiti in testo ASCII.

**kwds
Valori iniziali per le proprietà dell'istanza, come argomenti delle parole chiave. Ogni nome corrisponde a un attributo della nuova istanza e deve corrispondere alle proprietà fisse definite nella classe PolyModel.

Metodi di classe

Oltre ai metodi di classe definiti dalla classe Model, la classe PolyModel fornisce i seguenti metodi di classe:

PolyModel.class_key()

Restituisce il nome della classe e i nomi di tutte le classi padre della classe, sotto forma di tupla.

PolyModel.class_name()

Restituisce il nome del corso. Una classe può ignorare questo metodo se il nome della classe Python cambia, ma le entità devono continuare a utilizzare il nome della classe originale.