Clase de modelo NDB

Una clase que hereda de la clase Model representa la estructura de las entidades almacenadas en Datastore. Las aplicaciones definen clases de modelo para indicar la estructura de sus entidades y, a continuación, instancian esas clases de modelo para crear entidades. Todas las clases de modelo deben heredar (directa o indirectamente) de Model.

Esta página contiene documentación de referencia de la API. Para obtener una descripción general, consulta Entidades y claves de NDB.

Introducción

Una clase que hereda de Model describe las entidades de Datastore.

Todas las clases de modelo deben heredar (directa o indirectamente) de Model. Se pueden usar asignaciones sencillas en la definición de la clase de modelo para declarar la estructura del modelo:

from google.appengine.ext import ndb

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

Ahora podemos crear una entidad Person y escribirla en Datastore:

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

El valor devuelto de put() es una clave, que se puede usar para recuperar la misma entidad más adelante:

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

Para actualizar una entidad, solo tienes que cambiar sus atributos y volver a escribirla (ten en cuenta que esto no cambia la clave):

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

También podemos eliminar una entidad (usando la clave):

k.delete()

Las definiciones de propiedades del cuerpo de la clase indican al sistema los nombres y los tipos de los campos que se van a almacenar en Datastore, si deben indexarse, su valor predeterminado y más. Hay muchos tipos de propiedades.

El valor de kind suele ser igual al nombre de la clase (sin incluir el nombre del módulo ni ningún otro ámbito superior). Para anular el tipo (útil para los cambios de esquema), define un método de clase llamado _get_kind() de la siguiente manera:

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

Una aplicación no debe definir dos clases de modelo con el mismo tipo, aunque estén en módulos diferentes. Los tipos de una aplicación se consideran un "espacio de nombres" global.

Las subclases de Model pueden definir hooks previos y posteriores a las llamadas para la mayoría de las operaciones (get, put, delete, allocate_ids).

Constructor

Normalmente, una aplicación no llamará a Model(), pero es probable que llame al constructor de una clase que herede de Model. De esta forma, se crea una instancia de este modelo, también conocida como entidad.

La entidad recién creada no se escribe automáticamente en Datastore. Para que esto ocurra, debe escribirse en Datastore mediante una llamada explícita a put().

Argumentos:

Las subclases de Model admiten estos argumentos de palabras clave:

clave
Instancia
clave de este modelo. Si se usa el parámetro key, id y parent deben ser None (el valor predeterminado).
id
ID de clave de este modelo. Si se usa id, la clave debe ser None (el valor predeterminado).
parent
Instancia de
clave del modelo superior o None de uno de nivel superior. Si se usa parent, key debe ser None.
namespace
Espacio de nombres que se va a usar para esta entidad o None (valor predeterminado) para usar el espacio de nombres actual. Si se usa namespace, key debe ser None.

Una aplicación también puede usar argumentos de palabras clave que se asignen a las propiedades del modelo. Por ejemplo, lo siguiente funciona:

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

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

No puedes definir fácilmente una propiedad llamada "key", "id", "parent" o "namespace". Por ejemplo, si pasa key="foo" en un constructor o una llamada populate(), se define la clave de la entidad, no un atributo de propiedad llamado "key".

Nota: Si anulas el constructor en una subclase de Model, ten en cuenta que el constructor también se llama implícitamente en algunos casos. Asegúrate de que admites esas llamadas. Cuando se lee una entidad de Datastore, primero se crea una entidad vacía llamando al constructor sin argumentos. Después, se definen la clave y los valores de las propiedades uno a uno. Cuando get_or_insert() o get_or_insert_async() crea una instancia, pasa **constructor_args al constructor y, después, define la clave.

Métodos de clase

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

Asigna un intervalo de IDs de clave a esta clase de modelo.

Argumentos

size
Número de IDs que se van a asignar. Se puede especificar size o max, pero no ambos.
max
ID máximo que se puede asignar. Se puede especificar size o max, pero no ambos.
parent
Clave principal para la que se asignarán los IDs.
**ctx_options
Opciones de contexto

Devuelve una tupla con (inicio, fin) del intervalo asignado, ambos incluidos.

Una aplicación no puede llamar a allocate_ids() en una transacción.

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

Versión asíncrona de allocate_ids.

Devuelve un objeto Future cuyo resultado es una tupla con (inicio, fin) del intervalo asignado, ambos incluidos.

get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
Devuelve una entidad por ID. Se trata de una abreviatura de Key(cls, id).get().

Argumentos

id
ID de clave de cadena o entero.
parent
Clave superior del modelo que se va a obtener.
app (argumento de palabra clave)
ID de la aplicación. Si no se especifica, se obtienen los datos de la aplicación actual.
namespace (argumento de palabra clave)
Espacio de nombres. Si no se especifica, obtiene los datos del espacio de nombres predeterminado.
**ctx_options
Opciones de contexto

Devuelve una instancia del modelo o None si no se encuentra.

get_by_id_async(id, parent=None, app=None, namespace=None, **ctx_options)
Versión asíncrona de get_by_id.

Devuelve un objeto Future cuyo resultado es una instancia del modelo o None si no se encuentra.

get_or_insert(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
Recupera de forma transaccional una entidad o crea una.

Argumentos

key_name
Nombre de la clave (es decir, un ID de clave de cadena) que se va a recuperar o crear.
parent
Clave de la entidad superior, si procede.
aplicación
ID de la aplicación. Si no se especifica, se obtienen los datos de la aplicación actual.
namespace
Espacio de nombres. Si no se especifica, obtiene los datos del espacio de nombres predeterminado.
context_options
Opciones de contexto

Esta función también toma argumentos de palabras clave para pasarlos al constructor de la clase de modelo si aún no existe una instancia para el nombre de clave especificado. Si ya existe una instancia con el key_name y el elemento superior proporcionados, se descartarán estos argumentos.

Devuelve una instancia de la clase Model con el nombre de clave y el elemento superior especificados o una nueva que se acaba de crear.

Esta función usa una transacción. Si el código que llama a esta función ya está en una transacción, esta función intenta reutilizar la transacción. Si el grupo de entidades de esta función no es compatible con la transacción, se puede producir un error.

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

Esta es la versión asíncrona de get_or_insert.

Devuelve un objeto Future cuyo resultado es una instancia de la clase Model con el nombre de clave y el elemento superior especificados, o bien una instancia nueva que se acaba de crear.

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

Crea un objeto Query para esta clase, tal como se describe en Consultas.

El argumento de palabra clave distinct es una abreviatura de group_by = projection. Todos los demás argumentos de palabras clave se pasan al constructor Query.

Si se proporcionan argumentos posicionales, se usan para configurar los filtros iniciales.

Devuelve un objeto Query.

Métodos de instancia

populate(**constructor_options)

Define los valores de las propiedades de la entidad. Sus argumentos de palabras clave reconocen automáticamente los nombres de las propiedades de la misma forma que el constructor.

put(**ctx_options)

Escribe los datos de la entidad en Datastore. Devuelve la clave de la entidad.

Argumentos

**ctx_options
Opciones de contexto
put_async(**ctx_options)

Escribe de forma asíncrona los datos de la entidad en Datastore. Devuelve un objeto Future. El resultado del objeto Future será la clave de la entidad.

Argumentos

**ctx_options
Opciones de contexto
to_dict(include=all, exclude=None)

Devuelve un dict que contiene los valores de las propiedades del modelo. Los valores de las propiedades StructuredProperty y LocalStructuredProperty se convierten de forma recursiva en diccionarios.

Argumentos:

incluir
Lista opcional de propiedades que se van a incluir. Valor predeterminado: all.
exclude
Lista opcional de propiedades que se van a excluir. Si hay solapamiento entre incluir y excluir, entonces excluir "gana".

Nota: Si el valor de una propiedad es un objeto mutable (por ejemplo, una lista que representa una propiedad repetida o un diccionario o una lista almacenados en un JsonProperty), a menos que el valor se convierta explícitamente (por ejemplo, en el caso de un StructuredProperty), se devolverá el mismo objeto en el diccionario que se almacena en la entidad. En estos casos, si se modifica el diccionario, se modificará la entidad y viceversa.

Datos de instancia

clave
Propiedad especial para almacenar la clave del modelo.

Métodos de gancho

La subclase Model de una aplicación puede definir uno o varios de estos métodos como métodos "gancho" previos o posteriores a la operación. Por ejemplo, para ejecutar código antes de cada "get", define el método _pre_get_hook() de la subclase del modelo. Para obtener consejos sobre cómo escribir funciones de enlace, consulta Enlaces de modelos.

@classmethod
_pre_allocate_ids_hook(cls, size, max, parent)
Hook que se ejecuta antes allocate_ids()
@classmethod
_post_allocate_ids_hook(cls, size, max, parent, future)
Hook que se ejecuta después de allocate_ids()
@classmethod
_pre_delete_hook(cls, key)
Hook que se ejecuta antes delete()
@classmethod
_post_delete_hook(cls, key, future)
Hook que se ejecuta después de delete()
@classmethod
_pre_get_hook(cls, key)
Hook que se ejecuta antes Key.get() al obtener una entidad de este modelo.
@classmethod
_post_get_hook(cls, key, future)
Hook que se ejecuta después de Key.get() al obtener una entidad de este modelo.
_pre_put_hook(self)
Hook que se ejecuta antes put()
_post_put_hook(self, future)
Hook que se ejecuta después de put()

Introspección

Puede usar estos métodos para inspeccionar las propiedades y la configuración de un modelo concreto. Esto resulta útil si estás escribiendo una biblioteca o una función que acepta varios tipos de modelos.

Buscar por tipo

Todos los modelos tienen un tipo que suele ser el mismo que el nombre de la clase, a menos que se anule. Puedes usar el tipo para encontrar la clase de modelo asociada mediante _lookup_model.

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

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

Ten en cuenta que _lookup_model solo funciona con las clases de modelo que ya ha importado la aplicación.

Propiedades

Puedes obtener una lista de todas las propiedades asociadas a un modelo mediante _properties.

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

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

_properties también funciona con instancias de 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)}

Se pueden introspeccionar las instancias de propiedad. Las opciones proporcionadas al constructor están disponibles como propiedades con el prefijo _.

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étodo

Todos los métodos de la clase Model tienen un alias con el prefijo _. Por ejemplo, _put() es equivalente a put(). Esto significa que puedes tener propiedades con nombres que entren en conflicto con nombres de métodos, siempre que utilices los métodos con el prefijo _. Sin embargo, no puedes especificar ninguna propiedad con los nombres key, parent o id en el constructor.

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 creas bibliotecas de terceros que interactúan con modelos arbitrarios, te recomendamos que utilices los métodos con el prefijo _.