Classe de modelo NDB

Uma classe herdada da classe Model representa a estrutura de entidades armazenadas no Datastore. Os aplicativos definem classes de modelo para indicar a estrutura das entidades deles e instanciam essas classes de modelo para criar entidades. Todas as classes de modelo precisam herdar (direta ou indiretamente) de Model.

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

Introdução

Uma classe herdada de Model descreve entidades do Datastore.

Todas as classes de modelo precisam herdar (direta ou indiretamente) de Model. As atribuições diretas na definição da classe de 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()

Já podemos criar uma entidade Person e gravá-la no Datastore:

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

O valor de retorno de put() é uma chave, que pode ser usada para recuperar a mesma entidade posteriormente:

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

Para atualizar uma entidade, basta alterar os atributos dela e regravá-la (isso não altera a chave):

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

Também podemos excluir uma entidade usando a chave:

k.delete()

As definições de propriedade no corpo da classe informam ao sistema os nomes e os tipos dos campos a serem armazenados no Datastore, se precisam ser indexados, o valor padrão deles e muito mais. Existem muitos tipos Property diferentes.

O kind normalmente é igual ao nome da classe (exclusivo do nome do módulo ou de qualquer outro escopo pai). Para modificar o tipo (útil para alterações feitas no esquema), defina um método de classe denominado _get_kind() da seguinte forma:

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

Um aplicativo não precisará definir duas classes de modelo com o mesmo tipo, mesmo se elas residirem em módulos diferentes. Os tipos de um aplicativo são considerados um "namespace" global.

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

Construtor

Um aplicativo normalmente não chamará Model(), mas provavelmente chamará o construtor de uma classe herdada de Model. Isso cria uma nova instância desse modelo, também conhecida como entidade.

A entidade recém-criada não é gravada automaticamente no Datastore. Para que isso aconteça, ela precisa ser gravada no Datastore usando-se uma chamada explícita a put().

Argumentos:

As subclasses Model aceitam estes argumentos de palavra-chave:

key
Instância de Key deste modelo. Se o parâmetro key for usado, id e parent precisarão ser None (o padrão).
id
Código da chave deste modelo. Se id for usado, a chave precisará ser None (o padrão).
parent
Instância de Key para o modelo pai ou None para um modelo de nível superior. Se parent for usado, key precisará ser None.
namespace
Namespace a ser usado para essa entidade ou None (padrão) para usar o namespace atual. Se namespace for usado, key precisará ser None.

Um aplicativo também pode usar o mapeamento de argumentos de palavra-chave para as propriedades do modelo. Por exemplo, o seguinte código funciona:

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

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

Não é fácil definir uma propriedade denominada "key", "id", "parent" ou "namespace". Se você passar, por exemplo, key="foo" em um construtor ou populate(), ele definirá a chave da entidade, e não um atributo de propriedade denominado "key".

Observação: se você modificar o construtor em uma subclasse Model, saiba que o construtor também é chamado implicitamente em alguns casos e verifique se há compatibilidade com essas chamadas. Quando uma entidade é lida a partir do Datastore, primeiro uma entidade vazia é criada ao chamar o construtor sem argumentos. Depois, os valores de chave e propriedade são definidos individualmente. Quando get_or_insert() ou get_or_insert_async() cria uma nova instância, ele transmite **constructor_args para o construtor e depois define a chave.

Métodos de classe

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

Aloca um intervalo de códigos de chave para esta classe de modelo.

Argumentos

size
Número de códigos a serem alocados. É possível especificar size ou max, mas não ambos.
max
Código máximo a ser alocado. É possível especificar size ou max, mas não ambos.
parent
Chave pai a que os códigos serão alocados.
**ctx_options
Opções de contexto

Retorna uma tupla com (start, end) do intervalo alocado, inclusive.

Um aplicativo não pode chamar allocate_ids() em uma transação.

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

Versão assíncrona de allocate_ids.

Retorna um objeto Future com um resultado que é uma tupla com (start, end) referente ao intervalo alocado, inclusive.

get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
Retorna uma entidade por código. Na verdade, é apenas uma forma abreviada de Key(cls, id).get().

Argumentos

id
O código de uma string ou chave de inteiro.
parent
Chave pai do modelo a ser recebida.
app (keyword arg)
Código do app. Se não for especificado, receberá dados do app atual.
namespace (keyword arg)
Namespace. Se não especificado, receberá dados do namespace padrão.
**ctx_options
Opções de contexto

Retorna uma instância de modelo ou None, caso não encontrado.

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

Retorna um objeto Future com um resultado que é uma instância de modelo ou None, caso não encontrado.

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

Argumentos

key_name
Um nome de chave (ou seja, um código da chave de string) a ser recuperado ou criado.
parent
Chave de entidade pai, caso haja alguma.
app
Código do app. Se não for especificado, receberá dados do app atual.
namespace
Namespace. Se não especificado, receberá dados do namespace padrão.
context_options
Opções de contexto

Esta função também utiliza argumentos de palavra-chave a serem passados para o construtor da classe de modelo, caso uma instância do nome da chave especificada ainda não exista. Se uma instância com o key_name fornecido e o pai já existirem, esses argumentos serão descartados.

Retorna uma instância existente da classe Model com o nome da chave especificada e pai ou um novo recém-criado.

Esta função usa uma transação. Se o código que chama esta função já estiver em uma transação, ela tentará reutilizar a transação existente. Se o grupo de entidades desta função for incompatível com a transação existente, poderá causar 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.

Ela retorna um objeto Future com um resultado que é uma instância existente da classe Model com o nome da chave especificada e o pai ou um novo recém-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 essa classe, conforme descrito em Consultas.

O argumento de palavra-chave distinct é a forma abreviada de group_by = projection. Todos os outros argumentos de palavra-chave são passados para o construtor Query.

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

Retorna um objeto Query.

Métodos de instância

populate(**constructor_options)

Define valores das propriedades da entidade. Os argumentos de palavra-chave reconhecem automaticamente nomes de propriedade da mesma maneira que o construtor.

put(**ctx_options)

Grava os dados da entidade no Datastore. Retorna a chave da entidade.

Argumentos

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

Grava de maneira assíncrona os dados da entidade no Datastore. Retorna um objeto Future. O resultado do objeto Future será a Key da entidade.

Argumentos

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

Retorna um dict que contém os valores de propriedade do modelo. Os valores de propriedade de StructuredProperty e LocalStructuredProperty são convertidos de maneira recursiva em dicionários.

Argumentos:

include
Lista opcional de propriedades a serem incluídas. Padrão: tudo.
exclude
Lista opcional de propriedades a serem excluídas. Se houver sobreposição entre include e exclude, exclude "ganhará".

Observação: se o valor de uma propriedade for um objeto mutável (por exemplo, uma lista que representa uma propriedade repetida ou um dict ou lista armazenada em um JsonProperty), a menos que o valor seja explicitamente convertido (por exemplo, no caso de um StructuredProperty), o mesmo objeto será retornado no dict armazenado na entidade. Nesses casos, mudar o dicionário alterará a entidade e vice-versa.

Dados da instância

key
Propriedade especial para armazenar a chave Model.

Métodos de gancho

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

@classmethod
_pre_allocate_ids_hook(cls, size, max, parent)
Hook executado antes de allocate_ids()
@classmethod
_post_allocate_ids_hook(cls, size, max, parent, future)
Hook executado depois de allocate_ids()
@classmethod
_pre_delete_hook(cls, key)
Hook executado antes de delete()
@classmethod
_post_delete_hook(cls, key, future)
Hook executado depois de delete()
@classmethod
_pre_get_hook(cls, key)
Hook executado antes de Key.get() durante a recuperação de uma entidade deste modelo.
@classmethod
_post_get_hook(cls, key, future)
Hook executado depois de Key.get() durante a recuperação de uma entidade deste modelo.
_pre_put_hook(self)
Hook executado antes de put()
_post_put_hook(self, future)
Hook executado depois de put()

Introspecção

Você pode usar esses métodos para inspecionar as propriedades e a configuração de um determinado modelo. Isso será útil se você estiver escrevendo uma biblioteca ou uma função que aceite vários tipos de modelos.

Pesquisa por tipo

Cada modelo tem um tipo que costuma ser igual ao nome da classe, a menos que seja modificado. Você pode usar o tipo para encontrar a classe de modelo associada usando _lookup_model.

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

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

_lookup_model só funciona em classes de modelo já importadas pelo aplicativo.

Propriedades

Recupere uma lista de todas as propriedades associadas a um modelo usando _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 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 propriedade podem ser introspectivas. As opções fornecidas para o 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étodo

Cada método na classe Model tem um alias com o prefixo _. Por exemplo, _put() equivale a put(). Isso significa que você pode ter propriedades com nomes que entrem em conflito com nomes de método, desde que use sempre os métodos com o prefixo _. No entanto, não é possível especificar propriedades denominadas 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.

Para criar bibliotecas de terceiros que interagem com modelos arbitrários, recomendamos usar os métodos com prefixo "_".

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Ambiente padrão do App Engine para Python 2