NDB-Modellklasse

Eine Klasse, die der Model-Klasse untergeordnet ist, stellt die Struktur ihrer im Datenspeicher enthaltenen 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 später dieselbe Entität 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). Wenn Sie die Art überschreiben möchten (nützlich für Schemaänderungen), definieren Sie folgendermaßen 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(), sondern den Konstruktor einer Klasse, die Model untergeordnet ist, auf. 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:

Abgeleitete Model-Klassen unterstützen die folgenden Schlüsselwortargumente:

key
Schlüsselinstanz für dieses Modell. Wenn der Parameter key verwendet wird, müssen id und parent gleich None (Standardwert) sein.
id
Schlüssel-ID für dieses Modell. Wenn id verwendet wird, muss der Schlüssel gleich None (Standardwert) sein.
parent
Schlüsselinstanz für das übergeordnete Modell oder None für ein Modell auf oberster Ebene. Wenn parent verwendet wird, muss key gleich None sein.
namespace
Namespace, der für diese Entität verwendet werden soll, oder None (Standardwert), um den aktuellen Namespace zu verwenden. Wenn namespace verwendet wird, muss key gleich 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" an einen Konstruktor oder populate()-Aufruf übergeben, wird der Schlüssel der Entität festgelegt, nicht jedoch das Property-Attribut namens "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 erstellen, 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. Geben Sie entweder size oder max an, nicht jedoch beide Werte.
max
Maximale zuzuweisende ID. Geben Sie entweder size oder max an, nicht jedoch beide Werte.
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 in einer Transaktion nicht allocate_ids() 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 einfach 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 Anwendung. Wenn nicht angegeben, werden Daten für die aktuelle Anwendung abgerufen.
namespace (Schlüsselwortargument)
Namespace. Wenn nicht angegeben, werden Daten für den Standard-Namespace abgerufen.
**ctx_options
Kontextoptionen

Gibt eine Modellinstanz oder None zurück, wenn keine gefunden wird.

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

Gibt das Objekt Future zurück, dessen Ergebnis eine Modellinstanz ist, oder None, wenn keine 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 Anwendung. Wenn nicht angegeben, werden Daten für die aktuelle Anwendung 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 bereitgestellten 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, die gerade erstellt wurde, zurück.

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 das Objekt Query für diese Klasse, wie unter Abfragen beschrieben.

Das Schlüsselwortargument distinct ist eine Abkürzung 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 das Objekt Query 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 das Objekt Future zurück. Das Ergebnis des Objekts Future ist der Schlüssel der Entität.

Argumente

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

Gibt ein dict zurück, das die Property-Werte des Modells enthält. Property-Werte 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 das gleiche Objekt, das in der Entität gespeichert ist, in dem Wörterbuch zurückgegeben. In solchen Fällen wird durch Mutieren des Wörterbuchs die Entität mutiert und umgekehrt.

Instanzdaten

key
Spezielle Property 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 beim Abrufen einer Entität dieses Modells vor Key.get() ausgeführt wird.
@classmethod
_post_get_hook(cls, key, future)
Hook, der beim Abrufen einer Entität dieses Modells nach Key.get() ausgeführt 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. Anhand der Art können Sie die zugehörige Modellklasse ermitteln. Verwenden Sie dazu _lookup_model.

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 mit Modellklassen kompatibel ist, die bereits von der Anwendung importiert wurden.

Attribute

Mit _properties können Sie eine Liste aller Attribute aufrufen, die einem Modell zugeordnet sind.

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

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

_properties ist auch mit Expando-Instanzen kompatibel.

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 Model-Klasse hat einen Alias mit dem Präfix _. Beispiel: _put() entspricht 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, dass im Konstruktor keine Attribute mit dem Namen key, parent oder id angegeben werden dürfen.

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.