Classe PolyModel

Remarque : Les développeurs qui créent des applications sont vivement encouragés à utiliser la bibliothèque cliente NDB qui présente plusieurs avantages supplémentaires par rapport à cette bibliothèque cliente, tels que la mise en cache automatique des entités via l'API Memcache. Si vous utilisez actuellement l'ancienne bibliothèque cliente DB, consultez le guide de migration de DB vers NDB.

La classe PolyModel est la superclasse des définitions de modèles de données qui peuvent elles-mêmes représenter des super-classes d'autres définitions de modèles de données. Une requête générée à partir d'une classe PolyModel peut renvoyer des résultats correspondant à des instances de la classe ou de l'une de ses sous-classes.

La classe PolyModel est fournie par le module google.appengine.ext.db.polymodel.

PolyModel, qui est une sous-classe de Model, hérite de cette classe ses méthodes d'instance et de classe. La classe PolyModel remplace plusieurs méthodes de la classe Model, mais elle n'introduit aucun nouvel élément d'interface.

Présentation

Il s'avère souvent judicieux de définir les modèles de données comme une arborescence de classification, à la manière d'une base de données d'objets qui définit une classe d'objets en tant que sous-classe d'une autre. Ce type de base de données peut effectuer des requêtes sur des objets de la classe parente et inclure des objets de la sous-classe dans les résultats. L'App Engine Datastore ne prend pas en charge ce type de requête de manière native, mais vous pouvez l'implémenter à l'aide d'un mécanisme inclus dans le SDK Python, la classe PolyModel.

Une classe Model dérivée de PolyModel peut servir de classe de base pour d'autres classes Model. Les requêtes créées pour ces classes à l'aide des méthodes all() et gql() savent qu'elles doivent inclure des instances des sous-classes dans les résultats.

Les sous-classes peuvent définir de nouvelles propriétés qui n'existent pas dans les classes parentes. Toutefois, les sous-classes ne peuvent pas écraser des définitions de propriétés de classes parentes (Cette opération génère une erreur DuplicateProperty.)

À titre de référence, voici l'exemple simple tiré de la page Entités et modèles. Notez que la classe PolyModel est fournie par le package 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.
  # ...

Le polymorphisme n'est pas une fonctionnalité native du datastore. Au lieu de cela, le polymorphisme est implémenté au sein même de la classe PolyModel. Toutes les entités créées à partir des sous-classes PolyModel sont stockées dans le datastore avec le même genre, qui est le nom de la classe racine (par exemple, Animal). Chaque objet stocke sa hiérarchie de classe en tant que propriété à valeurs multiples de l'entité nommée 'class'. Lorsque l'application crée une requête en utilisant une méthode all() ou gql() de la classe PolyModel, la requête inclut un filtre sur la propriété 'class' qui limite les résultats aux entités créées à partir de la classe ou de l'une de ses sous-classes.

Dans la mesure où PolyModel utilise une propriété de l'entité pour stocker des informations de classe, les index des requêtes polymorphiques doivent prendre en compte la propriété 'class'. Le filtre implicite est un filtre d'égalité, et peut être associé à d'autres filtres d'égalité et d'inégalité sur d'autres propriétés.

Remarque : La classe PolyModel utilise uniquement les noms des classes dans la propriété 'class', et non pas les chemins d'accès complets. Il est possible de créer des hiérarchies de classes comportant plusieurs nœuds du même nom, par exemple A → B et A → C → B. Une requête sur l'une renvoie des entités appartenant aux deux. De même, les requêtes pour A → B → C et A → C → B sont identiques d'un point de vue fonctionnel. Nous vous recommandons d'éviter de créer une seule hiérarchie de classes comportant plusieurs nœuds du même nom.

PolyModel ne prend pas en charge le remplacement de définitions de modèles de propriétés dans les sous-classes. Si une sous-classe tente de redéfinir une propriété définie dans une super-classe, la définition de classe génère une erreur DuplicatePropertyError.

PolyModel prend en charge l'héritage multiple, y compris l'héritage de plusieurs classes partageant une super-classe (l'héritage "en diamant"). Une classe ne peut pas hériter de deux classes définissant chacune une définition de modèle de propriété pour la même propriété (cela génèrerait une erreur DuplicatePropertyError). Cependant, une classe peut hériter de deux classes qui héritent à leur tour d'une définition de modèle de propriété identique de la part de la même super-classe.

PolyModel ne prend pas en charge les propriétés dynamiques, contrairement à Expando. Il n'existe pas d'équivalent du modèle PolyModel pour Expando.

Constructeur

Le constructeur de la classe PolyModel est défini comme suit :

class PolyModel(parent=None, key_name=None, **kwds)

Classe de modèles qui peut servir de super-classe à d'autres classes de modèles et dont les requêtes peuvent renvoyer comme résultats des instances de sous-classes. Tout comme la classe Model, la classe PolyModel doit être sous-classée pour définir le genre des entités de données.

La classe PolyModel, qui est une sous-classe de Model, hérite de ses méthodes ou les remplace.

Arguments

parent
Instance Model ou Key de l'entité parente de la nouvelle entité.
key_name

Nom de la nouvelle entité. Le nom fait partie de la clé primaire. Si la valeur est None, un identifiant généré par le système est utilisé comme clé.

La valeur de key_name ne doit pas commencer par un nombre et ne doit pas se présenter au format __*__. Si l'application utilise des données soumises par l'utilisateur en tant que noms de clés d'entité Datastore (telles qu'une adresse e-mail), elle doit d'abord nettoyer la valeur pour satisfaire ces exigences, par exemple en la préfixant à l'aide d'une chaîne connue telle que "key:".

Le nom key_name est stocké sous la forme d'une chaîne Unicode, avec les valeurs str converties en texte ASCII.

**kwds
Valeurs initiales des propriétés de l'instance, sous forme d'arguments de mot clé. Chaque nom correspond à un attribut de la nouvelle instance et doit correspondre aux propriétés fixes définies dans la classe PolyModel.

Méthodes des classes

En plus des méthodes de classe définies par la classe Model, la classe PolyModel fournit les méthodes suivantes :

PolyModel.class_key()

Renvoie le nom de la classe et les noms de toutes les classes parentes de la classe, sous la forme d'un tuple.

PolyModel.class_name()

Renvoie le nom de la classe. Une classe peut écraser cette méthode si le nom de la classe Python change, mais les entités doivent continuer d'utiliser le nom de la classe d'origine.