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, come la memorizzazione automatica nella cache delle entità tramite l'API Memcache. Se attualmente utilizzi la libreria client di DB precedente, leggi la guida alla migrazione da DB a NDB

La classe PolyModel è la superclasse per le definizioni del modello dei dati che può essere a sua volta superclasse per altre definizioni del modello dei dati. Una query prodotta da una classe PolyModel può avere risultati che sono istanze della classe o una qualsiasi delle sue sottoclassi.

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

PolyModel è una sottoclasse di Model da cui eredita i metodi di classe e istanza. La classe PolyModel sostituisce diversi metodi del modello, ma non introduce nuovi elementi dell'interfaccia.

Introduzione

Spesso è utile definire i modelli di dati come una gerarchia di classificazione, proprio come un database di oggetti può definire una classe di oggetti come una sottoclasse di un'altra. Un database di questo tipo può eseguire query su oggetti della classe padre e includere nei risultati oggetti della sottoclasse. 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 del modello derivata da PolyModel può essere la classe base per altre classi di modello. Le query create per queste classi utilizzando i metodi all() e gql() sanno di includere istanze di sottoclassi nei risultati.

Le sottoclassi possono definire nuove proprietà non presenti nelle classi principali. Tuttavia, le sottoclassi non possono sostituire le definizioni delle proprietà delle classi principali. Ciò determina un errore di tipo DuplicateProperty.

Come riferimento, ecco un semplice esempio della sezione Entità e modelli. Nota 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 implementato invece nella classe PolyModel stessa. Tutte le entità create dalle sottoclassi PolyModel sono archiviate nel datastore con lo stesso tipo, che è il nome della classe radice (ad es. Animal). Ogni oggetto archivia la propria gerarchia delle classi come proprietà a più valori 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 nella proprietà 'class' che limita i risultati alle entità create dalla classe o da qualsiasi sottoclasse.

Poiché PolyModel utilizza una proprietà dell'entità per archiviare le informazioni sulla classe, gli indici per le query polimorfiche devono includere la proprietà 'class'. Il filtro implicito è un filtro di uguaglianza e può essere combinato con altri filtri di uguaglianza e di disuguaglianza su 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 con lo stesso nome, ad esempio AB e ACB. Una query per uno restituirà le entità di entrambi. In modo analogo, le query per ABC e ACB sono identiche dal punto di vista funzionale. È meglio evitare di creare una singola gerarchia di classi con più nodi con lo stesso nome.

PolyModel non supporta l'override delle definizioni di modelli di proprietà nelle sottoclassi. Se una sottoclasse cerca di ridefinire una proprietà definita su una superclasse, la definizione della classe genera un DuplicatePropertyError.

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

PolyModel non supporta proprietà dinamiche, come Espandio. 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 di modello che può essere una superclasse di altre classi di modello e le cui query possono includere istanze di sottoclassi come risultati. Come per Model, è necessario creare sottoclassi della classe PolyModel per definire il tipo di entità dati.

PolyModel è una sottoclasse di Model ed eredita o esegue l'override dei propri metodi.

Argomenti

parent
L'istanza del modello o della chiave dell'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 nel formato __*__. Se la tua applicazione utilizza dati inviati dagli utenti come nomi di chiavi di entità del datastore (ad esempio un indirizzo email), per soddisfare questi requisiti l'applicazione deve prima sanificare il valore, ad esempio anteponendovi una stringa nota come "key:".

Un key_name viene memorizzato come stringa Unicode, con i valori str convertiti come 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 della classe

Oltre ai metodi 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 della classe. Una classe può sostituire questo metodo se il nome della classe Python cambia, ma le entità devono continuare a utilizzare il nome della classe originale.