Избранное | Русский | Войти

Класс PolyModel

Класс PolyModel является суперклассом для определения моделей данных, которые, в свою очередь, могут быть суперклассами для определения других моделей данных. Запросы, выполняемые из класса PolyModel, могут возвращать экземпляры класса и любых его подклассов.

PolyModel входит в модуль google.appengine.ext.db.polymodel.

PolyModel является подклассом класса Model и наследует его методы класса и экземпляра. Класс PolyModel переопределяет некоторые методы класса Model, но не содержит каких-либо новых элементов интерфейса.

Введение

Нередко бывает полезно определять модели данных в виде классификационной иерархии, так же как в базе данных объектов один класс объектов может быть определен как подкласс другого. Такая база данных может выполнять запросы к объектам родительского класса, включая в результаты объекты его подклассов. Хранилище данных App Engine не поддерживает такой тип запросов по умолчанию, но его можно реализовать с помощью механизма, имеющегося в SDK Python, класса PolyModel.

Класс модели, полученный из класса PolyModel, может быть базовым для других классов моделей. Запросы, создаваемые для таких классов с помощью методов all() и gql(), включают экземпляры подклассов в свои результаты.

В подклассах можно определять новые свойства, отсутствующие в родительских классах. Однако переопределять свойства родительских классов в подклассах нельзя. (Это приведет к возникновению ошибки DuplicateProperty.)

Рассмотрим простой пример из статьи Объекты и модели. Обратите внимание, что класс PolyModel предоставляется в пакете 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.
  # ...

В отличие от Expando, класс PolyModel не поддерживает динамические свойства. Эквивалента PolyModel для Expando не существует.

Полиморфизм не является естественной функцией хранилища данных. Вместо этого полиморфизм реализован в самом классе PolyModel. Все объекты, созданные из подклассов PolyModel, сохраняются в хранилище данных с тем же типом, который является названием корневого класса (например, Animal). Каждый объект сохраняет иерархию своих классов в виде свойства 'class' с несколькими значениями. Когда приложение создает запрос с помощью методов all() или gql() класса PolyModel, в этот запрос добавляется фильтр по свойству 'class', ограничивающий результаты объектами, созданными из класса и его подклассов.

Поскольку для хранения информации о классах PolyModel использует свойство объекта, индексы для полиморфических запросов должны содержать свойство 'class'. Подразумеваемый фильтр является фильтром равенства, и его можно комбинировать с фильтрами равенства и неравенства по другим свойствам.

Примечание. Класс PolyModel использует в свойстве 'class' только названия классов, а не полные пути. Можно создавать иерархии классов с несколькими узлами, имеющими одинаковые названия, например AB и ACB. Запрос к одной из них вернет объекты из обеих. Аналогичным образом, запросы ABC и ACB функционально являются идентичными. Не рекомендуется создавать узлы с одинаковыми названиями в одной иерархии классов.

Конструктор

Конструктор класса PolyModel определяется следующим образом:

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

Класс модели, который может являться суперклассом для других классов моделей и запросы которого могут возвращать в качестве результатов экземпляры его подклассов. Как и для класса Model, для класса PolyModel необходимо создать подкласс, чтобы задать тип объектов данных.

PolyModel является подклассом класса Model и наследует или переопределяет его методы.

Аргументы:

parent
Экземпляр класса Model или Key для объекта, который является родителем нового объекта.
key_name

Название нового объекта. Это название становится частью первичного ключа. Если значение – None, то в качестве ключа используется идентификатор, созданный системой.

Значение аргумента key_name не должно начинаться с цифры или иметь форму __*__. Если приложение использует в качестве названий ключей объектов хранилища данные, передаваемые пользователем, например адрес электронной почты, сначала оно должно проверить значение на соответствие этим требованиям и скорректировать его. Для этого можно добавить к значению определенный префикс, например строку "key:".

Значение аргумента key_name хранится в виде строки Unicode, при этом значения str преобразуются в текст ASCII.

**kw
Начальные значения свойств экземпляра в виде именованных аргументов. Каждое название соответствует атрибуту нового экземпляра и должно соответствовать фиксированным свойствам, определенным в классе PolyModel.

Методы класса

Помимо методов, определяемых классом Model, класс PolyModel обладает следующими методами:

PolyModel.class_key()

Возвращает название класса и названия всех его родительских классов в виде кортежа.

PolyModel.class_name()

Возвращает название класса. Класс может переопределить этот метод, если название класса Python меняется, а объектам необходимо использовать прежнее название этого класса.