Classe de modèle NDB

Une classe qui hérite de la classe Model représente la structure des entités stockées dans le datastore. Les applications définissent des classes de modèle qui spécifient la structure de leurs entités, puis les instancient pour créer des entités. Toutes les classes de modèle doivent hériter (directement ou indirectement) de Model.

La présente page contient une documentation de référence sur l'API. Si vous souhaitez obtenir une présentation, consultez Entités NDB et clés.

Présentation

Une classe qui hérite de la classe Model décrit des entités Datastore.

Toutes les classes de modèle doivent hériter (directement ou indirectement) de Model. Vous pouvez déclarer la structure d'un modèle à l'aide d'affectations simples dans la définition de la classe de modèle :

from google.appengine.ext import ndb

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

Vous pouvez maintenant créer une entité "Person" et l'écrire dans le datastore :

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

La valeur renvoyée par put() est une clé, qui peut être utilisée pour récupérer la même entité ultérieurement comme suit :

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

Pour mettre à jour une entité, il suffit de changer ses attributs et de la retransmettre (notez que cela ne modifie pas la clé) :

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

Si vous souhaitez supprimer une entité (à l'aide de la clé), vous pouvez utiliser la méthode suivante :

k.delete()

Les définitions de propriétés dans le corps de la classe indiquent au système les noms et les types des champs à stocker dans le datastore, s'ils doivent être indexés ou non, leur valeur par défaut, etc. Il existe un grand nombre de types de propriétés.

Le genre correspond généralement au nom de la classe (sans le modèle ou tout autre champ d'application parent). Pour remplacer le genre (ce qui peut être utile en cas de modification du schéma), définissez une méthode de classe nommée _get_kind(), comme suit :

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

Une application ne doit pas définir deux classes de modèle du même genre, même si elles se trouvent dans des modules différents. Les genres d'une application sont considérés comme un "espace de noms" global.

Les sous-classes Model peuvent définir des hooks à exécuter avant ou après un appel pour la plupart des opérations (get, put, delete, allocate_ids).

Constructeur

Une application n'appelle normalement pas Model(), mais elle est susceptible d'appeler le constructeur d'une classe qui hérite de Model. Cela crée une instance de ce modèle, aussi appelée entité.

L'entité nouvellement créée n'est pas automatiquement écrite dans le datastore. Vous devez pour cela appeler explicitement put().

Arguments :

Les sous-classes Model acceptent les arguments de mot clé suivants :

key
Instance Key de ce modèle. Si le paramètre key est utilisé, la valeur des arguments id et parent doit être définie sur None (valeur par défaut).
id
ID de clé associé ce modèle. Si l'argument id est utilisé, la valeur du paramètre "key" doit être définie sur None (valeur par défaut).
parent
Instance Key du modèle parent ou None s'il s'agit d'un modèle de niveau supérieur. Si parent est utilisé, key doit être None.
namespace
Espace de noms à utiliser pour cette entité, ou None (par défaut) pour utiliser l'espace de noms actuel. Si namespace est utilisé, key doit être None.

Une application peut également utiliser des arguments de mot clé mappés aux propriétés du modèle. Par exemple, le code suivant fonctionne :

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

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

Vous ne pouvez pas facilement définir une propriété nommée "key", "id", "parent" ou "namespace". Si vous transmettez, par exemple, key="foo" à un constructeur ou à un appel populate(), la clé de l'entité est définie, et non un attribut de propriété nommé "key".

Remarque : Si vous remplacez le constructeur dans une sous-classe Model, sachez que celui-ci est également appelé de manière implicite dans certains cas. Assurez-vous donc de pouvoir traiter ces appels. Lorsqu'une entité est lue à partir du datastore, une entité vide est d'abord créée en appelant le constructeur sans arguments, après quoi les valeurs de clé et de propriétés sont définies une par une. Lorsque get_or_insert() ou get_or_insert_async() crée une instance, il transmet **constructor_args au constructeur et définit ensuite la clé.

Méthodes des classes

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

Alloue une plage d'ID de clé pour cette classe de modèle.

Arguments

size
Nombre d'ID à allouer. Vous pouvez spécifier l'argument size ou max, mais pas les deux.
max
Nombre maximal d'ID à allouer. Vous pouvez spécifier l'argument size ou max, mais pas les deux.
parent
Clé parente pour laquelle les ID seront alloués.
**ctx_options
Options de contexte

Renvoie un tuple au format (début, fin) pour la plage allouée. Les valeurs de début et de fin sont incluses.

Une application ne peut pas appeler allocate_ids() dans une transaction.

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

Version asynchrone de la méthode allocate_ids.

Renvoie un objet Future dont le résultat est un tuple au format (début, fin) pour la plage allouée. Les valeurs de début et de fin sont incluses.

get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
Renvoie une entité par ID. Cette méthode est simplement un raccourci pour Key(cls, id).get().

Arguments

id
Chaîne ou ID de clé sous forme d'entier.
parent
Clé parente du modèle à récupérer.
app (argument de mot clé)
ID de l'application. S'il n'est pas spécifié, récupère les données de l'application actuelle.
namespace (argument de mot clé)
Espace de noms. S'il n'est pas spécifié, les données sont récupérées à partir de l'espace de noms par défaut.
**ctx_options
Options de contexte

Renvoie une instance de modèle ou None si aucune instance n'a été trouvée.

get_by_id_async(id, parent=None, app=None, namespace=None, **ctx_options)
Version asynchrone de la méthode get_by_id.

Renvoie un objet Future dont le résultat est une instance de modèle ou None si aucun objet n'a été trouvé.

get_or_insert(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
Récupère de manière transactionnelle une entité existante ou en crée une nouvelle.

Arguments

key_name
Nom de clé (ID de clé de chaîne) à récupérer ou à créer.
parent
Clé de l'entité parente, le cas échéant.
appli
ID de l'application. S'il n'est pas spécifié, récupère les données de l'application actuelle.
namespace
Espace de noms. S'il n'est pas spécifié, les données sont récupérées à partir de l'espace de noms par défaut.
context_options
Options de contexte

Cette fonction permet également de transmettre des arguments de mot clé au constructeur de la classe de modèle si une instance associée au nom de clé spécifié n'existe pas déjà. S'il y a déjà une instance possédant le nom key_name et le parent fournis, ces arguments sont ignorés.

Renvoie l'instance existante de la classe Model avec le nom de clé et le parent spécifiés, ou une instance nouvellement créée.

Cette fonction utilise une transaction. Si le code qui l'appelle se trouve déjà dans une transaction, cette fonction tente de réutiliser la transaction existante. Si le groupe d'entités de cette fonction est incompatible avec la transaction existante, cela peut entraîner une erreur.

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

Il s'agit de la version asynchrone de get_or_insert.

La méthode renvoie un objet Future dont le résultat est une instance existante de la classe Model avec le nom de clé et le parent spécifiés, ou un objet nouvellement créé.

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

Crée un objet Query pour cette classe, comme décrit dans la section Requêtes.

L'argument de mot-clé distinct est un raccourci pour group_by = projection. Tous les autres arguments de mot clé sont transmis au constructeur de la requête.

Si des arguments positionnels sont fournis, ils servent à configurer les filtres initiaux.

Renvoie un objet Query.

Méthodes des instances

populate(**constructor_options)

Définit les valeurs des propriétés de l'entité. Ses arguments de mot clé reconnaissent les noms de propriétés automatiquement, de la même manière que le constructeur.

put(**ctx_options)

Écrit les données de l'entité dans le datastore. Renvoie la clé de l'entité.

Arguments

**ctx_options
Options de contexte
put_async(**ctx_options)

Écrit de manière asynchrone les données de l'entité dans le datastore. Renvoie un objet Future. Le résultat de l'objet Future est la clé de l'entité.

Arguments

**ctx_options
Options de contexte
to_dict(include=all, exclude=None)

Renvoie un dict contenant les valeurs de propriété du modèle. Les valeurs de propriété de StructuredProperty et LocalStructuredProperty sont converties de manière récursive en dictionnaires.

Arguments :

include
Liste facultative de propriétés à inclure. Par défaut, toutes les propriétés sont incluses.
exclude
Liste facultative de propriétés à exclure. S'il y a un chevauchement entre les arguments include et exclude, l'argument exclude l'emporte.

Remarque : Si la valeur d'une propriété est un objet modifiable (par exemple une liste représentant une propriété répétée ou un dictionnaire ou une liste stockée dans un fichier JsonProperty), le même objet est renvoyé dans le dictionnaire stocké dans l'entité, sauf si la valeur est explicitement convertie (dans le cas d'une StructuredProperty, par exemple). La modification du dictionnaire entraîne alors la modification de l'entité, et inversement.

Données d'instance

key
Propriété spéciale permettant de stocker la clé Model.

Méthodes de hook

La sous-classe Model d'une application peut définir une ou plusieurs de ces méthodes en tant que méthodes "hook" avant ou après l'opération. Si vous souhaitez par exemple exécuter du code avant chaque opération "get", définissez la méthode _pre_get_hook() de la sous-classe de modèle. Si vous avez besoin de conseils pour écrire des fonctions de hook, consultez Utiliser des hooks de modèle.

@classmethod
_pre_allocate_ids_hook(cls, size, max, parent)
Hook qui s'exécute avant allocate_ids()
@classmethod
_post_allocate_ids_hook(cls, size, max, parent, future)
Hook qui s'exécute après allocate_ids()
@classmethod
_pre_delete_hook(cls, key)
Hook qui s'exécute avant delete()
@classmethod
_post_delete_hook(cls, key, future)
Hook qui s'exécute après delete()
@classmethod
_pre_get_hook(cls, key)
Hook qui s'exécute avant Key.get() lors de l'obtention d'une entité de ce modèle.
@classmethod
_post_get_hook(cls, key, future)
Hook qui s'exécute après Key.get() lors de l'obtention d'une entité de ce modèle.
_pre_put_hook(self)
Hook qui s'exécute avant put()
_post_put_hook(self, future)
Hook qui s'exécute après put()

Introspection

Ces méthodes vous permettent d'inspecter les propriétés et la configuration d'un modèle donné. Elles s'avèrent utiles si vous écrivez une bibliothèque ou une fonction qui accepte plusieurs types de modèles.

Recherche par genre

Chaque modèle possède un genre qui est généralement identique au nom de la classe, sauf s'il a été remplacé. Vous pouvez utiliser le genre pour rechercher la classe de modèle associée à l'aide de _lookup_model.

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

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

Notez que _lookup_model ne fonctionne que pour les classes de modèle qui ont déjà été importées par l'application.

Propriétés

Vous pouvez obtenir la liste de toutes les propriétés associées à un modèle à l'aide de l'option _properties.

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

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

_properties fonctionne également pour les instances 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)}

Les instances de propriétés peuvent être inspectées. Les options fournies au constructeur sont disponibles en tant que propriétés précédées de _.

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 de méthodes

Chaque méthode de la classe Model possède un alias précédé de _. Par exemple, _put() correspond à put(). Cela signifie que vous pouvez employer des noms de propriétés identiques aux noms de méthodes, à condition que vous utilisiez toujours les méthodes portant le préfixe "_". Toutefois, notez que vous ne pouvez pas spécifier de propriétés nommées key, parent ou id dans le constructeur.

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.

Si vous créez des bibliothèques tierces qui interagissent avec des modèles arbitraires, nous vous recommandons d'utiliser les méthodes avec le préfixe "_".