Una clase que se hereda de la clase Model
representa la estructura de las entidades almacenadas en Datastore.
Las aplicaciones definen las clases de modelo para indicar la estructura de sus entidades y, luego, crean instancias de esas clases de modelo a fin de formar entidades.
Todas las clases de modelo se deben heredar (directa o indirectamente) de Model.
Esta página tiene documentación de referencia de API. Para obtener una descripción general, consulta Claves y entidades de NDB.
Introducción
Una clase que se hereda de Model
describe las entidades de Datastore.
Todas las clases de modelo se 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 que se muestra 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 debes 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 se puede borrar una entidad (mediante la clave):
k.delete()
Las definiciones de propiedad en el cuerpo de la clase le indican al sistema los nombres y los tipos de los campos que se almacenarán en Datastore, así como si se deben indexar, su valor predeterminado y más. Existen muchos Tipos de propiedad.
En general, la categoría es la misma que el nombre de la clase (exclusivo del nombre del módulo o cualquier alcance superior). A fin de anular la categoría (útil para los cambios de esquema), define un método de clase denominado _get_kind()
, de la manera siguiente:
class MyModel(ndb.Model): @classmethod def _get_kind(cls): return 'AnotherKind'
Una aplicación no debe definir dos clases de modelo con la misma categoría, incluso si se alojan en módulos diferentes. Las categorías de una aplicación se consideran “espacio de nombres” global.
Las subclases de Model
pueden definir hooks previos y posteriores a la llamada en la mayoría de las operaciones (get, put, delete y allocate_ids).
Constructor
Por lo general, una aplicación no llamará a Model()
, pero es probable que llame al constructor de una clase que se hereda de Model
.
Esto crea una instancia nueva para este modelo, también conocida como entidad.
La entidad recién creada no se escribe de forma automática en Datastore.
Para que esto suceda, se debe escribir en Datastore mediante una llamada explícita a put()
.
Argumentos:
Las subclases Model
admiten los siguientes argumentos de palabras clave:
- key
- La instancia clave para este modelo. Si se usa el parámetro
key
,id
yparent
deben serNone
(el valor predeterminado). - id
- El ID de clave para este modelo. Si se usa
id
, la clave debe serNone
(el valor predeterminado). - parent
- La instancia clave para el modelo superior o
None
si se trata de uno de nivel superior. Si se usaparent
,key
debe serNone
. - namespace
- El espacio de nombres que se debe usar en esta entidad o
None
(valor predeterminado) para usar el espacio de nombres actual. Si se usanamespace
,key
debe serNone
.
Una aplicación también puede usar argumentos de palabras clave mapeados 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 con facilidad una propiedad denominada “key”, “id”, “parent” o “namespace”.
Por ejemplo, si pasas key="foo"
en un constructor o realizas una llamada a populate()
, se establece la clave de la entidad y no un atributo de propiedad llamado “key”.
Nota: Si anulas el constructor en una subclase Model, ten en cuenta que, en algunos casos, también se llama al constructor de manera implícita, y asegúrate de que admites esas llamadas. Cuando se lee una entidad en Datastore, primero se crea una entidad vacía mediante una llamada al constructor sin argumentos y, después, los valores de clave y propiedad se configuran uno por uno.
Cuando get_or_insert()
o get_or_insert_async()
crean una instancia nueva, se pasa **constructor_args al constructor y, luego, se establece la clave.
Métodos de clase
- allocate_ids(size=None, max=None, parent=None, **ctx_options)
-
Asigna un rango de ID de clave para esta clase de modelo.
Argumentos
- size
- Cantidad de ID que se asignarán. Se pueden especificar
size
omax
, pero no ambos. - max
- ID máximo que se asignará. Se pueden especificar
size
omax
, pero no ambos. - parent
- Clave superior para la que se asignarán los ID.
- **ctx_options
- Opciones de contexto
Muestra una tupla con (inicio, fin) inclusiva para el rango asignado.
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.
Muestra un objeto
Future
cuyo resultado es una tupla con (inicio, fin) para el rango asignado, inclusive. - get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
- Muestra una entidad por ID. Esta marca es solo una forma abreviada de
Key(cls, id).get()
.Argumentos
- id
- Un ID de clave de string o número entero.
- parent
- La clave superior del modelo que se obtendrá.
- app (argumento de palabra clave)
- El ID de la app. Si no se especifica, obtiene los datos de la app actual.
- namespace (argumento de palabra clave)
- Espacio de nombres. Si no se especifica, obtiene datos para el espacio de nombres predeterminado.
- **ctx_options
- Opciones de contexto
Muestra una instancia de modelo o
None
si no se encuentra una. - get_by_id_async(id, parent=None, app=None, namespace=None, **ctx_options)
- Versión asíncrona de get_by_id.
Muestra un objeto
Future
cuyo resultado es una instancia de modelo oNone
si no se encuentra una. - get_or_insert(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
- Recupera mediante una transacción una entidad existente o crea una nueva.
Argumentos
- key_name
- Un nombre de clave (es decir, un ID de clave de string) que se recuperará o creará.
- parent
- Clave de entidad principal, si existe.
- app
- El ID de la app. Si no se especifica, obtiene los datos de la app actual.
- namespace
- Espacio de nombres. Si no se especifica, obtiene datos para el espacio de nombres predeterminado.
- context_options
- Opciones de contexto
Esta función también usa argumentos de palabras clave a fin de pasar al constructor de la clase de modelo si no existe una instancia para el nombre de clave especificado. Si ya existe una instancia con el
key_name
y el superior proporcionado, se descartarán estos argumentos.Muestra la instancia existente de la clase
Model
con el nombre de clave y el 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, la función intenta usar de nuevo la transacción existente. Puede haber un error si el grupo de entidad de esta función no es compatible con la transacción existente.
- 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.
Muestra un objeto
Future
cuyo resultado es una instancia existente de la claseModel
con el nombre de clave y el superior especificados o una nueva que se acaba de crear. - query([filter1, filter2, ...,] ancestor=None,app=None,namespace=None,filters=None,orders=None,default_options=None,projection=Nonedistinct=Falsegroup_by=None)
-
Crea un objeto
Query
para esta clase como se describe en Consultas.El argumento de palabra clave
distinct
es la abreviatura de group_by = projection. Los demás argumentos de palabras clave se pasan al Constructor de consultas.Si se proporcionan argumentos de posición, se usan para configurar los filtros iniciales.
Muestra un objeto
Query
.
Métodos de instancia
- populate(**constructor_options)
-
Configura valores de las propiedades de entidad. Sus argumentos de palabras clave reconocen automáticamente los nombres de la propiedad de la misma manera que lo hace el constructor.
- put(**ctx_options)
-
Escribe los datos de la entidad en Datastore. Muestra la Clave de la entidad.
Argumentos
- **ctx_options
- Opciones de contexto
- put_async(**ctx_options)
-
Escribe de manera asíncrona los datos de la entidad en Datastore. Muestra un objeto
Future
. El resultado del objetoFuture
será la clave de la entidad.Argumentos
- **ctx_options
- Opciones de contexto
- to_dict(include=all, exclude=None)
-
Muestra un
dict
que contiene los valores de propiedad del modelo. Los valores de propiedad deStructuredProperty
yLocalStructuredProperty
se convierten en diccionarios de manera recurrente.Argumentos:
- include
- Lista opcional de las propiedades que se incluirán. Predeterminado: todas.
- exclude
- Lista opcional de las propiedades que se excluirán. Si include y exclude se superponen, entonces, exclude “toma precedencia”.
Nota: Si el valor de una propiedad es un objeto mutable (p. ej., una lista que represente una propiedad repetida o un diccionario o lista almacenados en una
JsonProperty
), se muestra el mismo objeto en el diccionario que está almacenado en la entidad, a menos que el valor se convierta de forma explícita (p. ej., en el caso de unaStructuredProperty
). En tales casos, si cambias el diccionario, cambiará la entidad y viceversa.
Datos de instancia
- key
- Propiedad especial para almacenar la clave Model.
Métodos de hook
La subclase de Model
de una aplicación puede definir uno o más de estos métodos como métodos de “hook” previos y posteriores a la operación.
P. ej., para ejecutar algún código antes de cada “get”, define el método _pre_get_hook()
de la subclase de modelo. Si deseas recibir asesoramiento para escribir funciones de hook, consulta Hooks de modelo.
- @classmethod
_pre_allocate_ids_hook(cls, size, max, parent) - Un hook que se ejecuta antes que
allocate_ids()
- @classmethod
_post_allocate_ids_hook(cls, size, max, parent, future) - Un hook que se ejecuta después que
allocate_ids()
- @classmethod
_pre_delete_hook(cls, key) - Un hook que se ejecuta antes que
delete()
- @classmethod
_post_delete_hook(cls, key, future) - Un hook que se ejecuta después que
delete()
- @classmethod
_pre_get_hook(cls, key) - Un hook que se ejecuta antes que
Key.get()
cuando se obtiene una entidad de este modelo. - @classmethod
_post_get_hook(cls, key, future) - Un hook que se ejecuta después que
Key.get()
cuando se obtiene una entidad de este modelo. - _pre_put_hook(self)
- Un hook que se ejecuta antes que
put()
- _post_put_hook(self, future)
- Un hook que se ejecuta después que
put()
Introspección
Puedes usar estos métodos para inspeccionar las propiedades y la configuración de un modelo especificado. Esto es útil si escribes una biblioteca o función que acepta varios tipos de modelos.
Cómo buscar por categoría
Cada modelo tiene una categoría que suele ser la misma que el nombre de la clase, a menos que se haya anulado. Puedes usar la categoría para buscar 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 para las clases de modelo que la aplicación ya importó.
Propiedades
Puedes obtener una lista de todas las propiedades asociadas con 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 para 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 puede hacer una introspección de las instancias de propiedad. Las opciones que se proporcionan 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
Cada método en la clase Model
tiene un alias con el prefijo _
. Por ejemplo, _put()
es equivalente a put()
. Esto significa que puedes tener propiedades con nombres que entran en conflicto con los nombres de métodos, siempre y cuando uses los métodos con el prefijo _
. Sin embargo, ten en cuenta que no puedes especificar propiedades denominadas 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.
Es recomendable usar los métodos con el prefijo _
si creas bibliotecas de terceros que interactúen con modelos arbitrarios.