Hinweis: Entwicklern von neuen Anwendungen wird dringend empfohlen, die NDB-Clientbibliothek zu verwenden. Diese bietet im Vergleich zur vorliegenden Clientbibliothek verschiedene Vorteile, z. B. das automatische Caching von Entitäten über die Memcache API. Wenn Sie derzeit die ältere DB-Clientbibliothek verwenden, finden Sie weitere Informationen im Leitfaden zur Migration von DB- zu NDB-Clientbibliotheken.
Die PolyModel-Klasse ist die übergeordnete Klasse für Datenmodelldefinitionen, die wiederum übergeordnete Klassen für andere Datenmodelldefinitionen sein können. Eine über eine PolyModel-Klasse erstellte Anfrage kann zu Ergebnissen führen, die Instanzen der Klasse oder ihrer Unterklassen sind.
PolyModel
wird vom Modul google.appengine.ext.db.polymodel
bereitgestellt.
PolyModel ist eine Unterklasse von Model und erbt die Klassen- und Instanzmethoden dieser Klasse. Mit der PolyModel-Klasse werden einige der Methoden der Klasse Model überschrieben, aber keine neuen Oberflächenelemente eingeführt.
Einführung
Häufig ist es hilfreich, Datenmodelle als Klassifizierungshierarchie zu definieren. Dies ähnelt der Art und Weise, wie mit Objektdatenbanken eine Objektklasse als Unterklasse einer anderen definiert werden kann. Mit so einer Datenbank können Sie Anfragen bei Objekten der übergeordneten Klasse durchführen, wobei in die Ergebnisse Objekte der Unterklasse einbezogen werden können. Nativ wird diese Art Anfrage vom App Engine-Datastore nicht unterstützt. Sie können sie aber mit einem Mechanismus im Python-SDK implementieren. Es ist die Klasse PolyModel
.
Eine von PolyModel
abgeleitete Modellklasse kann die Basisklasse für andere Modellklassen sein. Abfragen, die für diese Klassen mit den Methoden all()
und gql()
erstellt wurden, enthalten in den Ergebnissen Instanzen von Unterklassen.
Mit Unterklassen können Sie neue Attribute definieren, die in übergeordneten Klassen nicht vorhanden sind. Mit Unterklassen können Sie allerdings keine Attributdefinitionen von übergeordneten Klassen überschreiben. Dies führt zum Fehler DuplicateProperty
.
Als Referenz finden Sie hier ein einfaches Beispiel zu Entitäten und Modellen. Die Klasse PolyModel
wird vom Paket google.appengine.ext.db.polymodel
bereitgestellt.
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. # ...
Nativ weist der Datenspeicher keine Polymorphie auf. Stattdessen wird Polymorphie in der Klasse PolyModel
selbst implementiert. Alle Entitäten, die aus PolyModel
-Unterklassen erstellt wurden, werden im Datenspeicher desselben Typs gespeichert. Der Name des Datenspeichers ist dann der Name der Stammklasse (beispielsweise Animal
). Jedes Objekt speichert seine Klassenhierarchie als mehrwertiges Attribut der Entität 'class'
. Wenn die Anwendung eine Abfrage mit den Methoden all()
oder gql()
einer PolyModel
-Klasse erstellt, enthält die Abfrage einen Filter für das Attribut 'class'
. Dieses beschränkt Ergebnisse auf Entitäten, die aus der Klasse oder einer Unterklasse erstellt wurden.
Da PolyModel
Klasseninformationen in einem Attribut der Entität speichert, müssen Indexe für polymorphe Abfragen das Attribut 'class'
enthalten. Der implizierte Filter ist ein Gleichheitsfilter, der mit Gleichheits- und Ungleichheitsfiltern aus anderen Attributen kombiniert werden kann.
Hinweis: PolyModel verwendet im Attribut 'class'
nur die Namen der Klassen, aber nicht vollständige Pfade. Sie können auch Klassenhierarchien mit mehreren gleichnamigen Knoten wie A
→ B
und A
→ C
→ B
erstellen. Mit einer Anfrage für ein Element werden Entitäten für beide zurückgegeben. Ebenso sind Abfragen nach A
→ B
→ C
und A
→ C
→ B
funktional identisch. Sie sollten nicht einzelne Klassenhierarchie mit mehreren Knoten und denselben Namen erstellen.
PolyModel
unterstützt nicht das Überschreiben von Attributmodelldefinitionen in Unterklassen. Wenn eine Unterklasse versucht, ein Attribut neu zu definieren, das in einer Basisklasse definiert ist, löst die Klassendefinition einen DuplicatePropertyError
aus.
PolyModel
unterstützt die mehrfache Vererbung, einschließlich des Erbens von mehreren Klassen einer gemeinsamen Basisklasse ("Diamond"-Vererbung). Eine Klasse kann nicht von zwei Klassen erben, die jeweils eine Attributmodelldefinition für dasselbe Attribut definieren (dies würde einen DuplicatePropertyError
auslösen). Eine Vererbung von zwei Klassen, die dieselbe Attributmodelldefinition von derselben übergeordneten Klasse erben, ist jedoch möglich.
PolyModel
unterstützt keine dynamischen Attribute, wie es bei Expando der Fall ist. Es gibt in Expando
keine Entsprechung für PolyModel
.
Konstruktor
Der Konstruktor der PolyModel-Klasse ist wie folgt definiert:
- class PolyModel(parent=None, key_name=None, **kwds)
-
Eine Modellklasse, bei der es sich um eine übergeordnete Klasse anderer Modellklassen handeln kann, und deren Anfragen Instanzen von Unterklassen als Ergebnisse umfassen können. Wie bei Model müssen für die PolyModel-Klasse abgeleitete Klassen definiert werden, um den Typ der Datenentitäten zu definieren.
PolyModel ist eine abgeleitete Klasse von Model und erbt oder überschreibt vorhandene Methoden.
Argumente
- parent
- Die Modell- oder Schlüsselinstanz der Entität, die das übergeordnete Element der neuen Entität ist.
- key_name
-
Der Name der neuen Entität. Der Name wird Teil des primären Schlüssels. Falls der Wert
None
ist, wird für den Schlüssel eine vom System generierte ID verwendet.Der Wert für key_name darf nicht mit einer Ziffer beginnen und nicht in dieser Form vorliegen:
__*__
. Wenn Ihre Anwendung vom Nutzer gesendete Daten als Schlüsselnamen für Datenspeicherentitäten verwendet (beispielsweise eine E-Mail-Adresse), sollte die Anwendung zuerst den Wert bereinigen, beispielsweise durch Voranstellen eines bekannten Strings wie "key:", um diese Anforderungen zu erfüllen.Ein
key_name
wird als Unicode-String gespeichert, wobeistr
-Werte in ASCII-Text konvertiert werden. - **kwds
- Anfängliche Werte für die Attribute der Instanz als Keyword-Argumente. Jeder Name entspricht einem Attribut der neuen Instanz, der mit festen Properties übereinstimmen muss, die in der PolyModel-Klasse definiert sind.
Klassenmethoden
Zusätzlich zu den von der Model-Klasse definierten Klassenmethoden stellt die PolyModel-Klasse die folgenden Klassenmethoden bereit:
- PolyModel.class_key()
-
Gibt den Namen der Klasse und die Namen aller übergeordneten Klassen der Klasse als Tupel zurück.
- PolyModel.class_name()
-
Gibt den Namen der Klasse zurück. Sie können diese Methode mit Klassen überschreiben, wenn sich der Name der Python-Klasse ändert. Bei den Entitäten hingegen sollten Sie weiterhin den ursprünglichen Klassennamen verwenden.