Classe do modelo NDB

Uma classe que herda da classe Model representa a estrutura das entidades armazenadas no Datastore. As aplicações definem classes de modelos para indicar a estrutura das respetivas entidades e, em seguida, instanciam essas classes de modelos para criar entidades. Todas as classes de modelos têm de herdar (direta ou indiretamente) de Model.

Esta página tem documentação de referência da API. Para uma vista geral, consulte Entidades e chaves da NDB.

Introdução

Uma classe que herda de Model descreve entidades do Datastore.

Todas as classes de modelos têm de herdar (direta ou indiretamente) de Model. As atribuições simples na definição da classe do modelo podem ser usadas para declarar a estrutura do modelo:

from google.appengine.ext import ndb

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

Agora, podemos criar uma entidade Person e escrevê-la no Datastore:

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

O valor devolvido de put() é uma Key, que pode ser usada para obter a mesma entidade mais tarde:

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

Para atualizar uma entidade, basta alterar os respetivos atributos e reescrevê-los (tenha em atenção que isto não altera a chave):

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

Também podemos eliminar uma entidade (através da chave):

k.delete()

As definições de propriedades no corpo da classe indicam ao sistema os nomes e os tipos dos campos a armazenar no Datastore, se têm de ser indexados, o respetivo valor predefinido e muito mais. Existem muitos tipos de propriedades diferentes.

Normalmente, o tipo é igual ao nome da classe (excluindo o nome do módulo ou qualquer outro âmbito principal). Para substituir o tipo (útil para alterações ao esquema), defina um método de classe denominado _get_kind(), da seguinte forma:

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

Uma aplicação não deve definir duas classes de modelos com o mesmo tipo, mesmo que estejam em módulos diferentes. Os tipos de uma aplicação são considerados um "espaço de nomes" global.

Model As subclasses podem definir hooks pré-chamada e pós-chamada para a maioria das operações (get, put, delete, allocate_ids).

Construtor

Normalmente, uma aplicação não chama Model(), mas é provável que chame o construtor de uma classe que herda de Model. Isto cria uma nova instância deste modelo, também conhecida como entidade.

A entidade criada recentemente não é escrita automaticamente no Datastore. Para que isso aconteça, tem de ser escrito no Datastore através de uma chamada explícita para put().

Argumentos:

As subclasses Model suportam estes argumentos de palavras-chave:

key
Instância
chave para este modelo. Se o parâmetro key for usado, id e parent têm de ser None (a predefinição).
id
ID da chave para este modelo. Se for usado id, a chave tem de ser None (a predefinição).
parent
Instância Key para o modelo principal ou None para um modelo de nível superior.
Se usar parent, key tem de ser None.
namespace
Espaço de nomes a usar para esta entidade ou None (predefinição) para usar o espaço de nomes atual. Se usar namespace, key tem de ser None.

Uma aplicação também pode usar argumentos de palavras-chave que mapeiam para as propriedades do modelo. Por exemplo, o seguinte funciona:

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

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

Não pode definir facilmente uma propriedade com o nome "key", "id", "parent" ou "namespace". Se passar, por exemplo, key="foo" num construtor ou numa chamada populate(), define a chave da entidade e não um atributo de propriedade denominado "chave".

Nota: Se substituir o construtor numa subclasse Model, tenha em atenção que o construtor também é chamado implicitamente em alguns casos e certifique-se de que suporta essas chamadas. Quando uma entidade é lida a partir do Datastore, é criada primeiro uma entidade vazia chamando o construtor sem argumentos, após o que os valores de chave e propriedade são definidos um a um. Quando get_or_insert() ou get_or_insert_async() cria uma nova instância, transmite **constructor_args ao construtor e define a chave posteriormente.

Métodos de classe

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

Atribui um intervalo de IDs de chaves a esta classe de modelo.

Argumentos

size
Número de IDs a atribuir. Pode especificar size ou max, mas não ambas.
max
ID máximo a atribuir. Pode especificar size ou max, mas não ambas.
parent
Chave principal para a qual os IDs vão ser atribuídos.
**ctx_options
Opções de contexto

Devolve uma tupla com (início, fim) para o intervalo atribuído, inclusive.

Uma aplicação não pode chamar allocate_ids() numa transação.

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

Versão assíncrona de allocate_ids.

Devolve um objeto Future cujo resultado é uma tupla com (start, end) para o intervalo atribuído, inclusive.

get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
Devolve uma entidade por ID. Isto é apenas uma abreviatura de Key(cls, id).get().

Argumentos

id
Um ID de chave de string ou inteiro.
parent
Chave principal do modelo a obter.
app (argumento de palavra-chave)
ID da app. Se não for especificado, recebe dados da app atual.
namespace (argumento de palavra-chave)
Espaço de nomes. Se não for especificado, recebe dados para o espaço de nomes predefinido.
**ctx_options
Opções de contexto

Devolve uma instância do modelo ou None se não for encontrada.

get_by_id_async(id, parent=None, app=None, namespace=None, **ctx_options)
Versão assíncrona de get_by_id.

Devolve um objeto Future cujo resultado é uma instância do modelo ou None se não for encontrado.

get_or_insert(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
Recupera transacionalmente uma entidade existente ou cria uma nova.

Argumentos

key_name
Um nome de chave (ou seja, um ID de chave de string) para obter ou criar.
parent
Chave da entidade principal, se existir.
app
ID da app. Se não for especificado, recebe dados da app atual.
namespace
Espaço de nomes. Se não for especificado, recebe dados para o espaço de nomes predefinido.
context_options
Opções de contexto

Esta função também recebe argumentos de palavras-chave para transmitir ao construtor da classe do modelo se ainda não existir uma instância para o nome da chave especificado. Se já existir uma instância com o key_name e o elemento principal fornecidos, estes argumentos são rejeitados.

Devolve a instância existente da classe Model com o nome da chave especificado e o elemento principal ou um novo que acaba de ser criado.

Esta função usa uma transação. Se o código que chama esta função já estiver numa transação, esta função tenta reutilizar a transação existente. Se o grupo de entidades desta função for incompatível com a transação existente, isto pode causar um erro.

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

Esta é a versão assíncrona de get_or_insert.

Devolve um objeto Future cujo resultado é uma instância existente da classe Model com o nome da chave especificado e o elemento principal ou um novo que acaba de ser criado.

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

Cria um objeto Query para esta classe, conforme descrito em Consultas.

O argumento da palavra-chave distinct é uma abreviatura de group_by = projection. Todos os outros argumentos de palavras-chave são transmitidos ao construtor de consultas.

Se forem fornecidos argumentos posicionais, estes são usados para configurar os filtros iniciais.

Devolve um objeto Query.

Métodos de instância

populate(**constructor_options)

Define os valores das propriedades da entidade. Os respetivos argumentos de palavras-chave reconhecem automaticamente os nomes das propriedades da mesma forma que o construtor.

put(**ctx_options)

Escreve os dados da entidade no Datastore. Devolve a chave da entidade.

Argumentos

**ctx_options
Opções de contexto
put_async(**ctx_options)

Escreve de forma assíncrona os dados da entidade no Datastore. Devolve um objeto Future. O resultado do objeto Future vai ser a chave da entidade.

Argumentos

**ctx_options
Opções de contexto
to_dict(include=all, exclude=None)

Devolve um dict que contém os valores das propriedades do modelo. Os valores das propriedades para StructuredProperty e LocalStructuredProperty são convertidos recursivamente em dicionários.

Argumentos:

incluir
Lista opcional de propriedades a incluir. Predefinição: todos.
excluir
Lista opcional de propriedades a excluir. Se existir uma sobreposição entre incluir e excluir, então excluir "ganha".

Nota: se o valor de uma propriedade for um objeto mutável (por exemplo, uma lista que representa uma propriedade repetida ou um dicionário ou uma lista armazenada num JsonProperty), a menos que o valor seja convertido explicitamente (por exemplo, no caso de um StructuredProperty), é devolvido o mesmo objeto no dicionário armazenado na entidade. Nestes casos, a alteração do dicionário altera a entidade e vice-versa.

Dados da instância

key
Propriedade especial para armazenar a chave do modelo.

Métodos de chamarizes

Uma subclasse de Model de uma aplicação pode definir um ou mais destes métodos como métodos de "gancho" pré ou pós-operação. Por exemplo, para executar algum código antes de cada "get", defina o método _pre_get_hook() da subclasse do modelo. Para obter conselhos sobre como escrever funções de gancho, consulte Ganchos de modelos.

@classmethod
_pre_allocate_ids_hook(cls, size, max, parent)
Hook que é executado antes de allocate_ids()
@classmethod
_post_allocate_ids_hook(cls, size, max, parent, future)
Hook que é executado após allocate_ids()
@classmethod
_pre_delete_hook(cls, key)
Hook que é executado antes de delete()
@classmethod
_post_delete_hook(cls, key, future)
Hook que é executado após delete()
@classmethod
_pre_get_hook(cls, key)
Hook que é executado antes de Key.get() quando recebe uma entidade deste modelo.
@classmethod
_post_get_hook(cls, key, future)
Hook que é executado após Key.get() quando recebe uma entidade deste modelo.
_pre_put_hook(self)
Hook que é executado antes de put()
_post_put_hook(self, future)
Hook que é executado após put()

Introspeção

Pode usar estes métodos para inspecionar as propriedades e a configuração de um determinado modelo. Isto é útil se estiver a escrever uma biblioteca ou uma função que aceite vários tipos de modelos.

Procura por tipo

Cada modelo tem um tipo que é normalmente igual ao nome da classe, a menos que seja substituído. Pode usar o tipo para encontrar a classe do modelo associada através de _lookup_model.

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

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

Tenha em atenção que _lookup_model só funciona para classes de modelos que já tenham sido importadas pela aplicação.

Propriedades

Pode obter uma lista de todas as propriedades associadas a um modelo através de _properties.

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

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

_properties também funciona para instâncias do 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)}

As instâncias de propriedades podem ser analisadas. As opções fornecidas ao construtor estão disponíveis como propriedades com o prefixo _.

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

Aliases de métodos

Todos os métodos na classe Model têm um alias com o prefixo _. Por exemplo, _put() é equivalente a put(). Isto significa que pode ter propriedades com nomes que entrem em conflito com os nomes dos métodos, desde que use sempre os métodos com o prefixo _. No entanto, tenha em atenção que não pode especificar nenhuma propriedade com o nome key, parent ou id no construtor.

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.

Se estiver a criar bibliotecas de terceiros que interagem com modelos arbitrários, é recomendável usar os métodos com o prefixo _-.