La clase PolyModel

Nota: Se recomienda enfáticamente a los desarrolladores que compilan aplicaciones nuevas que usen la biblioteca cliente de NDB, ya que tiene muchas ventajas en comparación con esta biblioteca cliente, como el almacenamiento en caché automático de entidades mediante la API de Memcache. Si por el momento usas la biblioteca cliente de DB anterior, lee la Guía de migración de DB a NDB.

La clase PolyModel es la superclase para definiciones de modelos de datos que, a su vez, pueden ser superclases de otras definiciones de modelos de datos. Una consulta producida a partir de una clase PolyModel puede tener resultados que son instancias de la clase o de cualquiera de sus subclases.

El módulo google.appengine.ext.db.polymodel proporciona PolyModel.

La clase PolyModel es una subclase de Model, y hereda su clase y los métodos de instancia de esa clase. La clase PolyModel anula varios de los métodos de Model, pero no incorpora ningún elemento de interfaz nuevo.

Introducción

A menudo resulta útil definir los modelos de datos como una jerarquía de clasificación, de forma similar a la que una base de datos de objetos puede definir una clase de objetos como una subclase de otra. Este tipo de base de datos puede realizar consultas sobre objetos de la clase superior, así como incluir objetos de la subclase en los resultados. El almacén de datos de App Engine no admite este tipo de consulta de forma nativa, pero puedes implementarlo con la ayuda de un mecanismo incluido con el SDK de Python, la clase PolyModel.

Una clase de modelo derivada de PolyModel puede ser la clase de base para otras clases de modelos. Las consultas creadas para estas clases mediante los métodos all() y gql() saben incluir instancias de subclases en los resultados.

Las subclases pueden definir propiedades nuevas que no están presentes en las clases superiores. No obstante, las subclases no pueden anular correctamente las definiciones de las clases superiores. (Cuando pasa, se genera un error DuplicateProperty).

Como referencia, aquí te proporcionamos el ejemplo sencillo de Entidades y modelos. Observa que la clase PolyModel no la proporciona el paquete google.appengine.ext.db.polymodel.

from google.appengine.ext import db
from google.appengine.ext.db import polymodel

class Contact(polymodel.PolyModel):
    phone_number = db.PhoneNumberProperty()
    address = db.PostalAddressProperty()

class Person(Contact):
    first_name = db.StringProperty()
    last_name = db.StringProperty()
    mobile_number = db.PhoneNumberProperty()

class Company(Contact):
    name = db.StringProperty()
    fax_number = db.PhoneNumberProperty()

p = Person(phone_number='1-206-555-9234',
           address='123 First Ave., Seattle, WA, 98101',
           first_name='Alfred',
           last_name='Smith',
           mobile_number='1-206-555-0117')
p.put()

c = Company(phone_number='1-503-555-9123',
            address='P.O. Box 98765, Salem, OR, 97301',
            name='Data Solutions, LLC',
            fax_number='1-503-555-6622')
c.put()

for contact in Contact.all():
  # Returns both p and c.
  # ...

for person in Person.all():
  # Returns only p.
  # ...

El polimorfismo no es una característica nativa del almacén de datos. En cambio, el polimorfismo se implementa en la propia clase PolyModel. Todas las entidades creadas a partir de subclases PolyModel se almacenan en el almacén de datos con el mismo tipo, que es el nombre de la clase raíz (p. ej., Animal). Cada objeto almacena su jerarquía de clase como una propiedad con valores múltiples de la entidad llamada 'class'. Cuando la app crea una consulta con los métodos all() o gql() de una clase PolyModel, la consulta incluye un filtro en la propiedad 'class' que limita los resultados a las entidades creadas a partir de la clase o de cualquier subclase.

Debido a que PolyModel usa una propiedad de la entidad para almacenar información de clase, los índices de las consultas polimórficas deben admitir la propiedad 'class'. El filtro implícito es un filtro de igualdad, y se puede combinar con otros filtros de igualdad y filtros de desigualdad en otras propiedades.

Nota: PolyModel usa solo los nombres de las clases en la propiedad 'class', no en las rutas completas. Se pueden crear jerarquías de clases con varios nodos del mismo nombre, como AB y ACB. Una consulta sobre uno mostrará entidades de ambos. Asimismo, las consultas sobre ABC y ACB son funcionalmente idénticas. Se recomienda evitar crear una única jerarquía de clases con varios nodos con el mismo nombre.

La clase PolyModel no admite la anulación de las definiciones de modelo de propiedad en las subclases. Si una subclase intenta redefinir una propiedad que está definida en una superclase, la definición de clase genera un error DuplicatePropertyError.

La clase PolyModel admite herencia múltiple, incluida la herencia de varias clases que comparten una superclase (herencia "diamante"). Una clase no puede heredar de dos clases que establezcan una definición de modelo de propiedad para la misma propiedad (esto generaría un error DuplicatePropertyError). Sin embargo, una clase puede heredar de dos clases que heredan la misma definición de modelo de propiedad de la misma superclase.

PolyModel no admite propiedades dinámicas, a diferencia de como lo hace Expando. No existe un equivalente de PolyModel para Expando.

Constructor

El constructor de la clase PolyModel se define de la manera siguiente:

class PolyModel(parent=None, key_name=None, **kwds)

Una clase de modelo que puede ser una superclase para otras clases de modelo, y cuyas consultas pueden incluir instancias de subclases como resultados. Al igual que con Model, la clase PolyModel debe ser una subclase para definir el tipo de entidades de datos.

PolyModel es una subclase de Model, y hereda o anula sus métodos.

Argumentos

parent
La instancia Model o la instancia Key correspondientes a la entidad superior de la entidad nueva.
key_name

El nombre de la entidad nueva. El nombre forma parte de la clave primaria. Si el valor es None, se usa un ID generado por el sistema para la clave.

El valor de key_name no debe comenzar con un número y no debe tener el formato __*__. Si tu aplicación usa datos enviados por los usuarios como nombres de clave para entidades de almacén de datos (como una dirección de correo electrónico), primero la aplicación debería limpiar el valor, por ejemplo, mediante el agregado de un prefijo con una string conocida como “key:”, para cumplir con estos requisitos.

Un key_name se almacena como una string de Unicode, con valores str convertidos en texto ASCII.

**kwds
Valores iniciales para las propiedades de la instancia, como argumentos de palabra clave. Cada nombre se corresponde con un atributo de la instancia nueva, y se debe corresponder con las propiedades fijas definidas en la clase PolyModel.

Métodos de clase

Además de los métodos de clase definidos por la clase Model, la clase PolyModel proporciona los métodos de clase siguientes:

PolyModel.class_key()

Muestra el nombre de la clase y los nombres de todas las clases superiores correspondientes a la clase, como una tupla.

PolyModel.class_name()

Muestra el nombre de la clase. Una clase puede anular este método si el nombre de la clase Python cambia, pero las entidades deberían continuar usando el nombre de clase original.