La clase PolyModel

Nota: Se recomienda encarecidamente a los desarrolladores que creen aplicaciones nuevas que usen la biblioteca de cliente de NDB, que ofrece varias ventajas en comparación con esta biblioteca de cliente, como el almacenamiento automático en caché de entidades mediante la API Memcache. Si actualmente usas la biblioteca de cliente de DB anterior, consulta la guía de migración de DB a NDB.

La clase PolyModel es una superclase de definiciones de modelos de datos que a su vez pueden ser superclases de otras definiciones de modelos de datos. Una consulta producida a través de una clase PolyModel puede dar como resultado instancias de la propia clase o de cualquiera de sus subclases.

PolyModel lo proporciona el módulo google.appengine.ext.db.polymodel.

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

Introducción

Con frecuencia, resulta útil definir los modelos de datos como una jerarquía clasificatoria, casi del mismo modo que una base de datos de objetos puede definir una clase de objetos como una subclase de otra. Dicha base de datos puede realizar consultas sobre objetos de la clase principal e 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 implementarla mediante un mecanismo incluido en el SDK de Python, la clase PolyModel.

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

Las subclases pueden definir las nuevas propiedades que no están presentes en las clases principales. Sin embargo, las subclases no pueden sobrescribir las definiciones de las propiedades de las clases principales. Si lo haces, se producirá un error DuplicateProperty.

A modo de referencia, aquí tienes el ejemplo sencillo de Entidades y modelos. Ten en cuenta que la clase PolyModel se proporciona en 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 función nativa del almacén de datos, En su lugar, el polimorfismo se implementa en la propia clase PolyModel. Todas las entidades creadas a partir de subclases de PolyModel se almacenan en el almacén de datos con el mismo tipo, que es el nombre de la clase raíz (por ejemplo, Animal). Cada objeto almacena su jerarquía de clases como una propiedad de varios valores de la entidad denominada 'class'. Cuando la aplicación crea una consulta mediante el método 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.

Como 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 que puede combinarse con otros filtros de igualdad o de desigualdad para otras propiedades.

Nota: PolyModel solo usa los nombres de las clases en la propiedad 'class', no las rutas completas. Es posible crear jerarquías de clases con varios nodos del mismo nombre, como AB y ACB. Una consulta para una de ellas devolverá entidades de ambas. Del mismo modo, las consultas de ABC y ACB son funcionalmente idénticas. Es mejor no crear una jerarquía de clases única con varios nodos que tengan el mismo nombre.

PolyModel no admite la anulación de definiciones de modelos de propiedades en subclases. Si una subclase intenta redefinir una propiedad definida en una superclase, la definición de la clase genera un DuplicatePropertyError.

PolyModel admite la herencia múltiple, incluida la herencia de varias clases que comparten una superclase (herencia en forma de diamante). Una clase no puede heredar de dos clases que definan un modelo de propiedad para la misma propiedad (esto generaría un DuplicatePropertyError). Sin embargo, una clase puede heredar de dos clases que hereden el mismo modelo de propiedad de la misma superclase.

PolyModel no admite propiedades dinámicas, como Expando. No hay ningún equivalente de PolyModel para Expando.

Constructor

El constructor de la clase PolyModel se define del siguiente modo:

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 resultado. Al igual que 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 de Model o de Key de la entidad que es el elemento superior de la nueva entidad.
key_name

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

El valor de key_name no debe empezar por un número ni tener el formato __*__. Si tu aplicación usa datos enviados por los usuarios como nombres de clave de entidad de Datastore (por ejemplo, una dirección de correo electrónico), la aplicación debe sanear el valor primero, por ejemplo, añadiéndole un prefijo con una cadena conocida como "key:", para cumplir estos requisitos.

Un key_name se almacena como una cadena Unicode, con los valores str convertidos como texto ASCII.

**kwds
Valores iniciales de las propiedades de la instancia, como argumentos de palabras clave. Cada nombre corresponde a un atributo de la instancia nueva y debe corresponderse 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 siguientes métodos de clase:

PolyModel.class_key()

Este método de clase devuelve el nombre de la clase y los nombres de todas las clases principales de la clase en forma de tupla.

PolyModel.class_name()

Este método de clase devuelve el nombre de la clase. Si se modifica el nombre de la clase Python, se puede sobrescribir este método mediante una clase, pero las entidades seguirían utilizando el nombre de la clase original.