NDB-Modellklasse

Eine Klasse, die der Model-Klasse untergeordnet ist, stellt die Struktur der im Datenspeicher gespeicherten Entitäten dar. Anwendungen definieren Modellklassen, um die Struktur ihrer Entitäten anzugeben. Diese Modellklassen werden dann zum Erstellen von Entitäten verwendet. Alle Modellklassen müssen dem Modell (direkt oder indirekt) untergeordnet sein.

Sie finden auf dieser Seite die API-Referenzdokumentation. Eine Übersicht finden Sie unter NDB-Entitäten und -Schlüssel.

Einführung

Eine Klasse, die der Model-Klasse untergeordnet ist, beschreibt Datenspeicherentitäten.

Alle Modellklassen müssen der Model-Klasse (direkt oder indirekt) untergeordnet sein. Einfache Zuweisungen in der Modellklassendefinition können dazu verwendet werden, die Struktur des Modells zu deklarieren:

from google.appengine.ext import ndb

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

Sie können jetzt eine Personenentität erstellen und in den Datenspeicher schreiben:

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

Der Rückgabewert von put() ist ein Schlüssel, mit dem dieselbe Entität später abgerufen werden kann:

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

Wenn Sie ein Objekt aktualisieren möchten, ändern Sie einfach dessen Attribute und schreiben es zurück. Beachten Sie, dass der Schlüssel hierdurch nicht geändert wird.

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

Sie können auch eine Entität mit dem Schlüssel löschen:

k.delete()

Die Property-Definitionen im Klassentext teilen dem System die Namen und Typen der Felder mit, die im Datenspeicher gespeichert werden sollen, ob sie indexiert werden müssen sowie ihren Standardwert und weitere Informationen. Es gibt viele verschiedene Property-Typen.

Die Art entspricht normalerweise dem Klassennamen (ausschließlich des Modulnamens oder eines anderen übergeordneten Bereichs). Zum Überschreiben der Art (nützlich für Schemaänderungen), definieren Sie so eine Klassenmethode mit dem Namen _get_kind():

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

Eine Anwendung darf nicht zwei Modellklassen derselben Art definieren, auch dann nicht, wenn sich die Modellklassen in unterschiedlichen Modulen befinden. Die Arten einer Anwendung werden als globaler "Namespace" betrachtet.

Abgeleitete Model-Klassen können Hooks vor und nach dem Aufrufen der meisten Vorgänge  definieren (get, put, delete, allocate_ids).

Konstruktor

Eine Anwendung ruft normalerweise nicht Model() auf, ruft aber wahrscheinlich den Konstruktor einer Klasse ab, die Model untergeordnet ist. Hierdurch wird eine neue Instanz dieses Modells erstellt, die auch als Entität bezeichnet wird.

Die neu erstellte Entität wird nicht automatisch in den Datenspeicher geschrieben. Sie muss mithilfe eines expliziten Aufrufs von put() in den Datenspeicher geschrieben werden.

Argumente:

Model - Unterklassen unterstützen diese Schlüsselwortargumente:

key
Schlüsselinstanz für dieses Modell. Wenn der Parameter key verwendet wird, müssen id und parent die Standardeinstellung None haben.
id
Schlüssel-ID für dieses Modell. Wenn id verwendet wird, muss der Schlüssel die Standardeinstellung None haben.
parent
Schlüsselinstanz für das übergeordnete Modell oder None für ein Modell auf oberster Ebene. Wenn parent verwendet wird, muss key None sein.
Namespace
Namespace zur Verwendung für diese Entität oder die Standardeinstellung None, um den aktuellen Namespace zu verwenden. Wenn namespace verwendet wird, muss key None sein.

Eine Anwendung kann auch Schlüsselwortargumente verwenden, die den Properties des Modells zugeordnet sind. Siehe folgendes Beispiel:

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

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

Sie können nicht einfach eine Property namens "key", "id", "parent" oder "namespace" definieren. Wenn Sie beispielsweise key="foo" in einem Konstruktor oder populate()-Aufruf übergeben, wird der Schlüssel der Entität festgelegt, nicht das Attribut "key".

Hinweis: Wenn Sie den Konstruktor in einer abgeleiteten Modellklasse überschreiben, wird der Konstruktor in einigen Fällen auch implizit aufgerufen. Sie müssen diese Aufrufe unterstützen. Beim Lesen einer Entität aus dem Datenspeicher wird zuerst eine leere Entität erstellt, indem der Konstruktor ohne Argumente aufgerufen wird. Anschließend werden die Schlüsselwerte und Attributwerte nacheinander festgelegt. Wenn get_or_insert() oder get_or_insert_async() eine neue Instanz erstellt, wird **constructor_args an den Konstruktor übergeben. Anschließend wird der Schlüssel festgelegt.

Klassenmethoden

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

Ordnet dieser Modellklasse einen Bereich von Schlüssel-IDs zu.

Argumente

size
Anzahl der zuzuweisenden IDs. Es kann entweder size oder max angegeben werden, nicht beides.
Max
Maximale zuzuweisende ID. Es kann entweder size oder max angegeben werden, nicht beides.
parent
Übergeordneter Schlüssel, für den die IDs zugewiesen werden.
**ctx_options
Kontextoptionen

Gibt ein Tupel mit (start, end) für den zugewiesenen Bereich zurück. Der Bereich ist einschließlich.

Eine Anwendung kann allocate_ids() in einer Transaktion nicht aufrufen.

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

Asynchrone Version von allocate_ids.

Gibt das Objekt Future zurück, dessen Ergebnis ein Tupel mit (start, end) für den zugewiesenen Bereich ist. Der Bereich ist einschließlich.

get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
Gibt eine Entität nach ID zurück. Dies ist nur eine Abkürzung für Key(cls, id).get().

Argumente

id
Ein String oder eine Schlüssel-ID als Ganzzahl.
parent
Übergeordneter Schlüssel des abzurufenden Modells.
app (Schlüsselwortargument)
ID der App. Wenn nicht angegeben, werden Daten für die aktuelle App abgerufen.
namespace (Schlüsselwortargument)
Namespace. Wenn nicht angegeben, werden Daten für den Standard-Namespace abgerufen.
**ctx_options
Kontextoptionen

Gibt eine Modellinstanz zurück oder None, falls nicht gefunden.

get_by_id_async(id, parent=None, app=None, namespace=None, **ctx_options)
Asynchrone Version von get_by_id.

Gibt ein Future-Objekt zurück, dessen Ergebnis eine Modellinstanz ist, oder None, wenn es nicht gefunden wird.

get_or_insert(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
Ruft eine vorhandene Entität transaktional ab oder erstellt eine neue Entität.

Argumente

key_name
Ein Schlüsselname (eine String-Schlüssel-ID) zum Abrufen oder Erstellen.
parent
Übergeordneter Entitätenschlüssel, falls vorhanden.
app
ID der App. Wenn nicht angegeben, werden Daten für die aktuelle App abgerufen.
Namespace
Namespace. Wenn nicht angegeben, werden Daten für den Standard-Namespace abgerufen.
context_options
Kontextoptionen

Diese Funktion übernimmt auch Schlüsselwortargumente, die an den Konstruktor der Modellklasse übergeben werden, wenn eine Instanz für den angegebenen Schlüsselnamen noch nicht vorhanden ist. Wenn eine Instanz mit dem angegebenen key_name und dem übergeordneten Element bereits vorhanden ist, werden diese Argumente verworfen.

Gibt die vorhandene Instanz der Model-Klasse mit dem angegebenen Schlüsselnamen und dem übergeordneten Element oder eine neue Instanz zurück, die gerade erstellt wurde.

Diese Funktion verwendet eine Transaktion. Wenn der Code, der diese Funktion aufruft, bereits in einer Transaktion vorhanden ist, versucht diese Funktion, die vorhandene Transaktion noch einmal zu verwenden. Wenn die Entitätengruppe dieser Funktion mit der vorhandenen Transaktion nicht kompatibel ist, kann dies zu einem Fehler führen.

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

Dies ist die asynchrone Version von get_or_insert.

Gibt das Objekt Future zurück, dessen Ergebnis eine vorhandene Instanz der Model-Klasse mit dem angegebenen Schlüsselnamen und dem übergeordneten Element oder eine neu erstellte Instanz ist.

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

Erstellt ein Query-Objekt für diese Klasse, wie unter Abfragen beschrieben.

Das Keyword-Argument distinct steht für group_by = projection. Alle anderen Schlüsselwortargumente werden an den Abfragekonstruktor übergeben.

Wenn Positionsargumente vorgegeben sind, werden sie zum Einrichten anfänglicher Filter verwendet.

Gibt ein Query-Objekt zurück.

Instanzmethoden

populate(**constructor_options)

Legt Werte für die Properties der Entität fest. Die zugehörigen Schlüsselwortargumente erkennen Property-Namen automatisch auf dieselbe Weise wie der Konstruktor.

put(**ctx_options)

Schreibt die Daten der Entität in den Datenspeicher. Gibt den Schlüssel der Entität zurück.

Argumente

**ctx_options
Kontextoptionen
put_async(**ctx_options)

Schreibt die Daten der Entität asynchron in den Datenspeicher. Gibt ein Future-Objekt zurück. Das Ergebnis des Future-Objekts ist der Schlüssel der Entität.

Argumente

**ctx_options
Kontextoptionen
to_dict(include=all, exclude=None)

Gibt ein dict zurück, das die Attributwerte des Modells enthält. Attributwerte für StructuredProperty und LocalStructuredProperty werden rekursiv in Wörterbücher umgewandelt.

Argumente:

include
Optionale Liste der einzuschließenden Properties. Standard: alle.
exclude
Optionale Liste der auszuschließenden Properties. Wenn es eine Überschneidung zwischen Einschließen und Ausschließen gibt, dann "gewinnt" Ausschließen.

Hinweis: Wenn ein Attributwert ein veränderbares Objekt ist (z. B. eine Liste, die ein wiederholtes Attribut darstellt, ein Wörterbuch oder eine Liste in einem JsonProperty) und der Wert nicht explizit umgewandelt wird (z. B. im Fall von StructuredProperty), wird im Wörterbuch das gleiche Objekt zurückgegeben, das in der Entität gespeichert ist. In solchen Fällen wird durch Mutieren des Wörterbuchs die Entität mutiert und umgekehrt.

Instanzdaten

key
Spezielles Attribut zum Speichern des Modellschlüssels.

Hook-Methoden

Die abgeleitete Model-Klasse einer Anwendung kann eine oder mehrere dieser Methoden als "Hook"-Methoden vor oder nach dem Vorgang definieren. Wenn Sie beispielsweise den gleichen Code vor jedem "get" ausführen möchten, definieren Sie die Methode _pre_get_hook() der abgeleiteten Modellklasse. Hinweise zum Schreiben von Hook-Funktionen finden Sie unter Modell-Hooks.

@classmethod
_pre_allocate_ids_hook(cls, size, max, parent)
Hook, der vor allocate_ids() ausgeführt wird
@classmethod
_post_allocate_ids_hook(cls, size, max, parent, future)
Hook, der nach allocate_ids() ausgeführt wird
@classmethod
_pre_delete_hook(cls, key)
Hook, der vor delete() ausgeführt wird
@classmethod
_post_delete_hook(cls, key, future)
Hook, der nach delete() ausgeführt wird
@classmethod
_pre_get_hook(cls, key)
Hook, der vor Key.get() ausgeführt wird, wenn eine Entität dieses Modells abgerufen wird.
@classmethod
_post_get_hook(cls, key, future)
Hook, der nach Key.get() ausgeführt wird, wenn eine Entität dieses Modells abgerufen wird.
_pre_put_hook(self)
Hook, der vor put() ausgeführt wird
_post_put_hook(self, future)
Hook, der nach put() ausgeführt wird

Introspektion

Sie können diese Methoden verwenden, um die Properties und die Konfiguration eines bestimmten Modells zu überprüfen. Dies ist nützlich, wenn Sie eine Bibliothek oder Funktion schreiben, die mehrere Typen von Modellen akzeptiert.

Nach Art suchen

Jedes Modell hat eine Art, die normalerweise dem Klassennamen entspricht, es sei denn, sie wird überschrieben. Sie können die Art verwenden, um die zugehörige Modellklasse mithilfe von _lookup_model zu finden.

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

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

Beachten Sie, dass _lookup_model nur für Modellklassen funktioniert, die bereits von der Anwendung importiert wurden.

Eigenschaften

Mit _properties können Sie eine Liste aller mit einem Modell verknüpften Attribute abrufen.

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

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

_properties funktioniert auch für Expando-Instanzen.

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)}

Attributinstanzen können auch einer Introspektion unterzogen werden. Die dem Konstruktor bereitgestellten Optionen sind als Attribute mit dem Präfix _ verfügbar.

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

Methodenaliasse

Jede Methode in der Klasse Model hat ein Alias mit dem Präfix _. _put() entspricht beispielsweise put(). Dies bedeutet, dass Attribute mit Namen vorhanden sein können, die mit Methodennamen in Konflikt stehen. Dies setzt jedoch voraus, dass Sie die Methoden immer mit dem Präfix _ verwenden. Beachten Sie jedoch, dass Sie keine Eigenschaften mit dem Namen key, parent oder id im Konstruktor angeben können.

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.

Wenn Sie Bibliotheken von Drittanbietern erstellen, die mit beliebigen Modellen interagieren, wird die Verwendung der Methoden mit dem Präfix _ empfohlen.