Classe modello NDB

Una classe che eredita dalla classe Model rappresenta la struttura delle entità archiviate nel datastore. Le applicazioni definiscono classi di modelli per indicare la struttura delle loro entità, quindi le eseguono per creare le entità. Tutte le classi di modelli devono ereditare (direttamente o indirettamente) da Model.

Questa pagina contiene la documentazione di riferimento dell'API. Per una panoramica, consulta Entità e chiavi NDB.

Introduzione

Una classe che eredita da Model descrive le entità di Datastore.

Tutte le classi di modelli devono ereditare (direttamente o indirettamente) da Model. È possibile utilizzare assegnazioni semplici nella definizione della classe del modello per dichiararne la struttura:

from google.appengine.ext import ndb

class Person(ndb.Model):
  name = ndb.StringProperty()
  age = ndb.IntegerProperty()

Ora possiamo creare un'entità Persona e scriverla nel Datastore:

p = Person(name='Arthur Dent', age=42)
k = p.put()

Il valore restituito da put() è una chiave, che può essere utilizzata per recuperare la stessa entità in un secondo momento:

p2 = k.get()
p2 == p  # Returns True

Per aggiornare un'entità, modifica semplicemente i relativi attributi e riscrivili (tieni presente che la chiave non viene modificata):

p2.name = 'Arthur Philip Dent'
p2.put()

Possiamo anche eliminare un'entità (utilizzando la chiave):

k.delete()

Le definizioni delle proprietà nel corpo della classe indicano al sistema i nomi e i tipi di campi da archiviare in Datastore, se devono essere indicizzati, il loro valore predefinito e altro ancora. Esistono molti tipi di proprietà.

kind è in genere uguale al nome della classe (escluso il nome del modulo o di qualsiasi altro ambito principale). Per eseguire l'override del tipo (utile per le modifiche dello schema), definisci un metodo di classe denominato _get_kind(), come segue:

  class MyModel(ndb.Model):
    @classmethod
    def _get_kind(cls):
      return 'AnotherKind'

Un'applicazione non deve definire due classi di modelli dello stesso tipo, anche se si trovano in moduli diversi. I tipi di un'applicazione sono considerati un "spazio dei nomi" globale.

Le sottoclassi Model possono definire hook pre-call e post-call per la maggior parte delle operazioni (get, put, delete, allocate_ids).

Costruttore

In genere, un'applicazione non chiama Model(), ma è probabile che chiamI il costruttore di una classe che eredita da Model. Viene creata una nuova istanza di questo modello, nota anche come entità.

L'entità appena creata non viene scritta automaticamente in Datastore. Per farlo, deve essere scritto in Datastore utilizzando una chiamata esplicita a put().

Argomenti:

Le sottoclassi di Model supportano questi argomenti della parola chiave:

chiave
Istanza
Key per questo modello. Se viene utilizzato il parametro key, id e parent devono essere None (il valore predefinito).
id
ID chiave per questo modello. Se viene utilizzato id, la chiave deve essere None (il valore predefinito).
parent
Istanza
Key per il modello principale o None per uno di primo livello. Se viene utilizzato parent, key deve essere None.
namespace
Spazio dei nomi da utilizzare per questa entità oppure None (predefinito) per utilizzare lo spazio dei nomi corrente. Se viene utilizzato namespace, key deve essere None.

Un'applicazione può anche utilizzare argomenti parola chiave che mappano alle proprietà del modello. Ad esempio, funziona quanto segue:

class Person(ndb.Model):
  name = StringProperty()
  age = IntegerProperty()

p = Person(name='Arthur Dent', age=42)

Non puoi definire facilmente una proprietà denominata "key", "id", "parent" o "namespace". Se passi, ad esempio, key="foo" in un costruttore o in una chiamata populate(), viene impostata la chiave dell'entità, non un attributo della proprietà denominato "chiave".

Nota: se sostituisci il costruttore in una sottoclasse Model, tieni presente che in alcuni casi il costruttore viene chiamato anche in modo implicito e assicurati di supportare queste chiamate. Quando un'entità viene letta da Datastore, viene prima creata un'entità vuota chiamando il costruttore senza argomenti, dopodiché i valori della chiave e delle proprietà vengono impostati uno alla volta. Quando get_or_insert() o get_or_insert_async() crea una nuova istanza, passa **constructor_args al costruttore e imposta la chiave in un secondo momento.

Metodi di classe

allocate_ids(size=None, max=None, parent=None, **ctx_options)

Alloca un intervallo di ID chiave per questa classe di modelli.

Argomenti

size
Numero di ID da allocare. Puoi specificare size o max, non entrambi.
max
ID massimo da allocare. Puoi specificare size o max, non entrambi.
parent
Chiave principale per la quale verranno assegnati gli ID.
**ctx_options
Opzioni di contesto

Restituisce una tupla con (start, end) per l'intervallo allocato, inclusi.

Un'applicazione non può chiamare allocate_ids() in una transazione.

allocate_ids_async(size=None, max=None, parent=None, **ctx_options)

Versione asincrona di allocate_ids.

Restituisce un oggetto Future il cui risultato è una tupla con (start, end) per l'intervallo allocato, inclusi.

get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
Restituisce un'entità in base all'ID. Si tratta solo di una rappresentazione abbreviata di Key(cls, id).get().

Argomenti

id
Un ID chiave di stringa o intero.
parent
Chiave principale del modello da recuperare.
app (arg parola chiave)
ID dell'app. Se non specificato, vengono recuperati i dati per l'app corrente.
namespace (arg parola chiave)
Spazio dei nomi. Se non specificato, vengono recuperati i dati per lo spazio dei nomi predefinito.
**ctx_options
Opzioni di contesto

Restituisce un'istanza del modello o None se non viene trovata.

get_by_id_async(id, parent=None, app=None, namespace=None, **ctx_options)
Versione asincrona di get_by_id.

Restituisce un oggetto Future il cui risultato è un'istanza del modello o None se non viene trovata.

get_or_insert(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
Recupero transazionale di un'entità esistente o creazione di una nuova.

Argomenti

key_name
Un nome chiave (ovvero un ID chiave di stringa) da recuperare o creare.
parent
Chiave dell'entità principale, se presente.
app
ID dell'app. Se non specificato, vengono recuperati i dati per l'app corrente.
namespace
Spazio dei nomi. Se non specificato, vengono recuperati i dati per lo spazio dei nomi predefinito.
context_options
Opzioni di contesto

Questa funzione accetta anche argomenti di parole chiave da passare al costruttore della classe del modello se non esiste già un'istanza per il nome della chiave specificato. Se esiste già un'istanza con key_name e parent forniti, questi argomenti verranno ignorati.

Restituisce l'istanza esistente della classe Model con il nome della chiave e il valore parent specificati o una nuova appena creata.

Questa funzione utilizza una transazione. Se il codice che chiama questa funzione è già in una transazione, questa funzione tenta di riutilizzare la transazione esistente. Se il gruppo di entità di questa funzione non è compatibile con la transazione esistente, può verificarsi un errore.

get_or_insert_async(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)

Questa è la versione asincrona di get_or_insert.

Restituisce un oggetto Future il cui risultato è un'istanza esistente della classe Model con il nome della chiave e il valore padre specificati o una nuova appena creata.

query([filter1, filter2, ...,] ancestor=None, app=None, namespace=None, filters=None, orders=None, default_options=None, projection=None distinct=False group_by=None)

Crea un oggetto Query per questo corso come descritto in Query.

L'argomento della parola chiave distinct è un'abbreviazione di group_by = projection. Tutti gli altri argomenti della parola chiave vengono passati al costruttore Query.

Se vengono forniti argomenti posizionali, vengono utilizzati per impostare i filtri iniziali.

Restituisce un oggetto Query.

Metodi istanza

populate(**constructor_options)

Imposta i valori delle proprietà dell'entità. I suoi argomenti delle parole chiave riconoscono automaticamente i nomi delle proprietà nello stesso modo in cui lo fa il costruttore.

put(**ctx_options)

Scrive i dati dell'entità in Datastore. Restituisce la chiave dell'entità.

Argomenti

**ctx_options
Opzioni di contesto
put_async(**ctx_options)

Scrive in modo asincrono i dati dell'entità in Datastore. Restituisce un oggetto Future. Il risultato dell'oggetto Future sarà la chiave dell'entità.

Argomenti

**ctx_options
Opzioni di contesto
to_dict(include=all, exclude=None)

Restituisce un dict contenente i valori delle proprietà del modello. I valori delle proprietà per StructuredProperty e LocalStructuredProperty vengono convertiti in modo ricorsivo in dizionari.

Argomenti:

include
Elenco facoltativo delle proprietà da includere. Valore predefinito: all.
exclude
Elenco facoltativo di proprietà da escludere. Se esiste una sovrapposizione tra include e exclude, exclude "vince".

Nota: se il valore di una proprietà è un oggetto mutabile (ad es. un elenco che rappresenta una proprietà ripetuta o un dizionario o elenco memorizzato in un JsonProperty), a meno che il valore non venga convertito esplicitamente (ad es. nel caso di un StructuredProperty), viene restituito lo stesso oggetto nel dizionario memorizzato nell'entità. In questi casi, la mutazione del dizionario comporterà la mutazione dell'entità e viceversa.

Dati istanza

chiave
Proprietà speciale per memorizzare la chiave del modello.

Metodi di hook

La sottoclasse di Model di un'applicazione può definire uno o più di questi metodi come metodi "hook" pre- o post-operazione. Ad esempio, per eseguire del codice prima di ogni "get", definisci il metodo _pre_get_hook() della sottoclasse del modello. Per consigli sulla scrittura di funzioni di hook, consulta Model Hooks.

@classmethod
_pre_allocate_ids_hook(cls, size, max, parent)
Hook eseguito prima allocate_ids()
@classmethod
_post_allocate_ids_hook(cls, size, max, parent, future)
Hook eseguito dopo allocate_ids()
@classmethod
_pre_delete_hook(cls, key)
Hook eseguito prima delete()
@classmethod
_post_delete_hook(cls, key, future)
Hook eseguito dopo delete()
@classmethod
_pre_get_hook(cls, key)
Hook che viene eseguito prima di Key.get() quando si ottiene un'entità di questo modello.
@classmethod
_post_get_hook(cls, key, future)
Hook che viene eseguito dopo Key.get() quando si ottiene un'entità di questo modello.
_pre_put_hook(self)
Hook eseguito prima put()
_post_put_hook(self, future)
Hook eseguito dopo put()

Introspezione

Puoi utilizzare questi metodi per ispezionare le proprietà e la configurazione di un determinato modello. Questa operazione è utile se stai scrivendo una libreria o una funzione che accetta più tipi di modelli.

Ricerca per tipo

Ogni modello ha un tipo che in genere corrisponde al nome della classe, a meno che non sia stato overridden. Puoi utilizzare il tipo per trovare la classe del modello associata utilizzando _lookup_model.

class Animal(ndb.Model):
    type = ndb.StringProperty()

print Animal._get_kind()  # 'Animal'
print ndb.Model._lookup_model('Animal')  # class Animal

Tieni presente che _lookup_model funziona solo per le classi di modelli già importate dall'applicazione.

Proprietà

Puoi ottenere un elenco di tutte le proprietà associate a un modello utilizzando _properties.

class User(ndb.Model):
    name = ndb.StringProperty()
    email = ndb.StringProperty()

print User._properties
# {'email': StringProperty('email'), 'name': StringProperty('name')}

_properties funziona anche per le istanze Expando.

class Example(ndb.Expando):
  pass

e = Example()
e.foo = 1
e.bar = 'blah'
e.tags = ['exp', 'and', 'oh']
print e._properties
# {'foo': GenericProperty('foo'), 'bar': GenericProperty('bar'),
# 'tags': GenericProperty('tags', repeated=True)}

Le istanze di proprietà possono essere sottoposte a ispezione. Le opzioni fornite al costruttore sono disponibili come proprietà con prefisso _.

print User._properties['email']._name  # 'email'
print User._properties['email']._required  # False
print User._properties['email']._default  # None
print User._properties['email']._choices  # None
print User._properties['email']._compressed  # False
print User._properties['email']._indexed  # True
print User._properties['email']._compressed  # False
print User._properties['email']._repeated  # False
print User._properties['email']._verbose_name  # None
print isinstance(User._properties['email'], ndb.StringProperty)  # True

Alias dei metodi

Ogni metodo della classe Model ha un alias con prefisso _. Ad esempio, _put() è equivalente a put(). Ciò significa che puoi avere proprietà con nomi in conflitto con i nomi dei metodi, a condizione di utilizzare sempre i metodi con prefisso _. Tuttavia, tieni presente che non puoi specificare proprietà denominate key, parent o id nel costruttore.

class MyModel(ndb.Model):
    put = ndb.StringProperty()
    query = ndb.StringProperty()
    key = ndb.StringProperty()

entity = MyModel()
entity.put = '1'
entity.query = '2'
entity.key = '3'

entity._put()
print entity
# MyModel(key=Key('MyModel', ...), put=u'1', query=u'2', key=u'3')

print MyModel._query().fetch()
# same as above.

Se crei librerie di terze parti che interagiscono con modelli arbitrari, ti consigliamo di utilizzare i metodi con prefisso _.