• Официальный сайт SDK
  • Сайт с примерами кода

Объекты и их модели

Каждый объект, помещаемый в хранилище, имеет ключ и определенный набор свойств. Для определения моделей данных и создания их экземпляров, которые сохраняются как объекты, приложение использует интерфейс Datastore API. Модели представляют собой общую структуру для работы с объектами и могут задавать правила по проверке допустимости данных значений свойств.

Объекты хранилища

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

Каждый объект также имеет уникальный ключ, по которому его однозначно можно идентифицировать. Простейший ключ содержит тип объекта и уникальный цифровой идентификатор, автоматически присвоенный ему хранилищем. По желанию разработчика идентификатором может выступать строка, указанная объекту приложением. Для дополнительной информации о ключах смотрите раздел Ключи и наборы объектов.

Приложение может получить определенный объект из хранилища, указав его идентификатор или выполнив специальный запрос, который удовлетворит значениям свойств этого объекта. В запросе также может быть задан ключ предка объекта, подробнее смотрите раздел Ключи и группы объектов. Запрос может вернуть ноль или несколько объектов, отсортированных по значениям указанных свойств. Для уменьшения объемов памяти и процессорного времени, требуемых на обработку результатов, возвращаемых из хранилища, в запросе можно установить ограничение числа их выдачи.

В отличии от традиционных реляционных баз данных, хранилище App Engine не требует того, чтобы объекты одного вида имели одинаковый набор типов свойств. Для доступа к данным приложение может задействовать специальный интерфейс.

Модели

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

Свойства модели могут быть определены с использованием атрибутов ее класса. Каждый такой атрибут является экземпляром потомка класса Property, который может быть одним из классов типов свойств. Экземпляр свойства объекта содержит в себе всю конфигурацию этого свойства, такую как необходимость проверки на допустимость присваемого значения или использования значения по умолчанию.

CmZyb20gZ29vZ2xlLmFwcGVuZ2luZS5leHQgaW1wb3J0IGRiCmNsYXNzIFBldChkYi5Nb2RlbCk6Cm5hbWUgPSBkYi5TdHJpbmdQcm9wZXJ0eShyZXF1aXJlZD1UcnVlKQp0eXBlID0gZGIuU3RyaW5nUHJvcGVydHkocmVxdWlyZWQ9VHJ1ZSwgY2hvaWNlcz1zZXQoWyJjYXQiLCAiZG9nIiwgImJpcmQiXSkpCmJpcnRoZGF0ZSA9IGRiLkRhdGVQcm9wZXJ0eSgpCndlaWdodF9pbl9wb3VuZHMgPSBkYi5JbnRlZ2VyUHJvcGVydHkoKQpzcGF5ZWRfb3JfbmV1dGVyZWQgPSBkYi5Cb29sZWFuUHJvcGVydHkoKQpvd25lciA9IGRiLlVzZXJQcm9wZXJ0eShyZXF1aXJlZD1UcnVlKQo==

После создания экземпляра класса определенной выше модели объекта, с ним можно будет работать с помощью интерфейса взаимодействия с хранилищем. Приложение может создать новый объект, вызвав конструктор этого класса. Также приложение сможет получить доступ и изменять свойства этого объекта, используя атрибуты экземпляра. При создании нового объекта конструктор модели может принимать начальные значения в качестве своих именованных аргументов.

CmZyb20gZ29vZ2xlLmFwcGVuZ2luZS5hcGkgaW1wb3J0IHVzZXJzCnBldCA9IFBldChuYW1lPSJGbHVmZnkiLAp0eXBlPSJjYXQiLApvd25lcj11c2Vycy5nZXRfY3VycmVudF91c2VyKCkpCnBldC53ZWlnaHRfaW5fcG91bmRzID0gMjQK=

Примечание: Атрибуты класса модели являются конфигурацией ее свойств и представляют собой значения экземпляров потомков классов Property. Атрибуты экземпляра модели являются реальными значениями свойств объекта, которые принимаются потомками классов Property.

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

Так как проверка на допустимость значений происходит при создании экземпляра свойства, для тех из них, которые требуют обязательного указания значений, они должны быть присвоены через параметры конструктора при создании нового объекта. К примеру, свойства name, type и owner требуют обязательного указания значений, таким образом их необходимо будет сразу присвоить при создании нового объекта, передав параметрами в конструктор. Свойство weight_in_pounds не является обязательным, поэтому объект можно создать без его указания и присвоить значение позже.

Обратите внимание, что после создания экземпляра модели с использованием ее конструктора, объект не будет сохранен в хранилище до тех пор, пока приложение явно не вызовет метод put. Смотрите раздел Создание, получение и удаление данных.

Примечание: Аналогично поведению обычных классов языка Python, конфигурация модели инициализируется в тот момент, когда первый раз загружается скрипт или модуль. Так как платформа App Engine использует механизм кэширования импортируемых модулей, конфигурация моделей будет проинициализирована только для первого пользователя и затем повторно использована для последующих запросов. По этой причине не присваивайте свойствам модели значений по умолчанию, специфических для текущего запроса. Смотрите раздел Кэширование для получения дополнительной информации.

Расширенные модели

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

Часто это бывает полезно для задания объектов одного типа, некоторые свойства которых могут быть определены, а могут быть и нет. Работа с такими объектами, представленными в хранилише, осуществляется с помощью расширенных ("expando") моделей. Расширенные модели являются потомками базового класса Expando. Любое значение, присвоенное атрибуту экземпляра класса расширенной модели, становится свойством объекта, помещенного в хранилище, с именем соответствующим атрибуту. Эти свойства называются динамическими свойствами. Свойства, описанные в модели с использованием потомков класса Property называются статическими свойствами.

Расширенные модели могут одновременно содержать как статические, так и динамические свойства. Класс модели содержит конфигурацию статических свойств, заданную с помощью экземпляров потомков классов Property. Приложение создает динамические свойства путем присваивания значений атрибутам модели.

CmNsYXNzIFBlcnNvbihkYi5FeHBhbmRvKToKZmlyc3RfbmFtZSA9IGRiLlN0cmluZ1Byb3BlcnR5KCkKbGFzdF9uYW1lID0gZGIuU3RyaW5nUHJvcGVydHkoKQpob2JiaWVzID0gZGIuU3RyaW5nTGlzdFByb3BlcnR5KCkKcCA9IFBlcnNvbihmaXJzdF9uYW1lPSJBbGJlcnQiLCBsYXN0X25hbWU9IkpvaG5zb24iKQpwLmhvYmJpZXMgPSBbImNoZXNzIiwgInRyYXZlbCJdCnAuY2hlc3NfZWxvX3JhdGluZyA9IDEzNTAKcC50cmF2ZWxfY291bnRyaWVzX3Zpc2l0ZWQgPSBbIlNwYWluIiwgIkl0YWx5IiwgIlVTQSIsICJCcmF6aWwiXQpwLnRyYXZlbF90cmlwX2NvdW50ID0gMTMK=

Так как динамические свойства не определяются с помощью описания класса модели, допустимость их значений не может быть проверена. Любое из динамических свойств может иметь одно из значений базовых типов, включая None. Два объекта одного типа могут иметь различные типы одного и того же динамического свойства, причем у одного из них оно может быть вообще не задано.

В отличии от статических свойств объекта, динамические у него могут не существовать. Однако, динамическое свойство со значением None отличается от несуществующего динамического свойства. Если экземпляр расширенной модели не имеет атрибут для свойства, то соответствующий ему объект с данными в хранилище также не будет иметь этого свойства. Вы можете удалить динамическое свойство путем удаления атрибута экземпляра модели.

CmRlbCBwLmNoZXNzX2Vsb19yYXRpbmcK=

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

CnAxID0gUGVyc29uKCkKcDEuZmF2b3JpdGUgPSA0MgpwMS5wdXQoKQpwMiA9IFBlcnNvbigpCnAyLmZhdm9yaXRlID0gImJsdWUiCnAyLnB1dCgpCnAzID0gUGVyc29uKCkKcDMucHV0KCkKcGVvcGxlID0gZGIuR3FsUXVlcnkoIlNFTEVDVCAqIEZST00gUGVyc29uIFdIRVJFIGZhdm9yaXRlICZsdDsgOjEiLCA1MCkKIyDQv9C10YDQtdC80LXQvdC90LDRjyBwZW9wbGUg0LHRg9C00LXRgiDRgdC+0LTQtdGA0LbQsNGC0YwgcDEsINC90L4g0L3QtSBwMiDQuNC70LggcDMKcGVvcGxlID0gZGIuR3FsUXVlcnkoIlNFTEVDVCAqIEZST00gUGVyc29uIFdIRVJFIGZhdm9yaXRlICZndDsgOjEiLCA1MCkKIyDQv9C10YDQtdC80LXQvdC90LDRjyBwZW9wbGUg0L3QtSDQsdGD0LTQtdGCINGB0L7QtNC10YDQttCw0YLRjCDRgNC10LfRg9C70YzRgtCw0YLQvtCyCg===

Класс Expando является потомком базового класса Model и наследует всего его методы.

Свойства и их типы

Хранилище поддерживает различные типы свойств для размещаемых в нем объектов, включающих строки типа юникод, целочисленные и дробные числа, даты, ссылки на другие объекты, бинарные двоичные данные (BLOB) и различные другие типы. Каждые из них представлен собственным классом, потомком класса Property, находящимся в модуле google.appengine.ext.db.

В разделе Классы типов свойств описаны все поддерживаемые типы и их классы. Некоторые специальные типы будут описаны ниже.

Строки, длинные строки и двоичные бинарные объекты

Хранилище поддерживает возможность сохранения двух типов текстовых строк: короткие строки, которые могут быть длиной меньше 500 байт, и длинные - больше 500 байт. Короткие строки индексируются и их содержимое может быть затем использовано в условиях запросов и сортировок. Напротив, длинные строки не индексируются и не могут выступать в параметрах запросов.

Значение короткой строки может быть либо типом unicode или str. При использовании типа str система задействует кодировку 'ascii'. Для указания другой кодировки строки типа str, вы можете сконвертировать ее в значение типа unicode, используя конструктор unicode(), который принимает в своих параметрах строку типа str и название кодировки. Тип коротких строк используется в определении модели путем указания класса StringProperty.

CmNsYXNzIE15TW9kZWwoZGIuTW9kZWwpOgpzdHJpbmcgPSBkYi5TdHJpbmdQcm9wZXJ0eSgpCm9iaiA9IE15TW9kZWwoKQojINCh0LjQvdGC0LDQutGB0LjRgSDRj9C30YvQutCwIFB5dGhvbiDQtNC70Y8g0LfQsNC00LDQvdC40Y8g0Y7QvdC40LrQvtC00L3QvtCz0L4g0YLQuNC/0LAg0YHRgtGA0L7QutC4LgpvYmouc3RyaW5nID0gdSJraXR0ZW5zIgojINC80LXRgtC+0LQgdW5pY29kZSgpINC60L7QvdCy0LXRgNGC0LjRgNGD0LXRgiDQsdCw0LnRgtC+0LLRg9GOINGB0YLRgNC+0LrRgyDQsiDQt9C90LDRh9C10L3QuNC1INGC0LjQv9CwINGO0L3QuNC60L7QtCDRgSDQuNGB0L/QvtC70YzQt9C+0LLQsNC90LjQtdC8INC30LDQtNCw0L3QvdC+0LPQviDQutC+0LTQtdC60LAuCm9iai5zdHJpbmcgPSB1bmljb2RlKCJraXR0ZW5zIiwgImxhdGluLTEiKQojINCt0YLQsCDQsdCw0LnRgtC+0LLQsNGPINGB0YLRgNC+0LrQsCDQsdGD0LTQtdGCINC/0YDQtdC00YHRgtCw0LLQu9C10L3QsCDQsiDQutC+0LTQuNGA0L7QstC60LUgQVNDSUkgKNC60L7QtNC10LogJ2FzY2lpJykuCm9iai5zdHJpbmcgPSAia2l0dGVucyIKIyDQodCy0L7QudGB0YLQstCwINGC0LjQv9CwINC60L7RgNC+0YLQutCw0Y8g0YHRgtGA0L7QutCwINC80L7QttC10YIg0LHRi9GC0Ywg0LjRgdC/0L7Qu9GM0LfQvtCy0LDQvdC+INCyINC/0LDRgNCw0LzQtdGC0YDQsNGFINC30LDQv9GA0L7RgdCwLgpyZXN1bHRzID0gZGIuR3FsUXVlcnkoIlNFTEVDVCAqIEZST00gTXlNb2RlbCBXSEVSRSBzdHJpbmcgPSA6MSIsIHUia2l0dGVucyIpCg===

Длинная строка задается с помощью экземпляра класса db.Text. Его конструктор принимает значение типа unicode или str и опционально имя кодека при использовании параметра типа str. Свойства для длинных строк задаются в модели с использованием класса TextProperty.

CmNsYXNzIE15TW9kZWwoZGIuTW9kZWwpOgp0ZXh0ID0gZGIuVGV4dFByb3BlcnR5KCkKb2JqID0gTXlNb2RlbCgpCiMgVGV4dCgpINC80L7QttC10YIg0L/RgNC40L3QuNC80LDRgtGMINGO0L3QuNC60L7QtNC90L7QtSDQt9C90LDRh9C10L3QuNC1LgpvYmoudGV4dCA9IGRiLlRleHQodSJsb3RzIG9mIGtpdHRlbnMiKQojIFRleHQoKSDQvNC+0LbQtdGCINC/0YDQuNC90LjQvNCw0YLRjCDQsdCw0LnRgtC+0LLRg9GOINGB0YLRgNC+0LrRgyDRgSDRg9C60LDQt9Cw0L3QuNC10Lwg0YLQuNC/0LAg0LrQvtC00LjRgNC+0LLQutC4LgpvYmoudGV4dCA9IGRiLlRleHQoImxvdHMgb2Yga2l0dGVucyIsICJsYXRpbi0xIikKIyDQkiDRgtC+0Lwg0YHQu9GD0YfQsNC1LCDQtdGB0LvQuCDQutC+0LTQuNGA0L7QstC60LAg0L3QtSDQt9Cw0LTQsNC90LAsINC60L7QtNC40YDQvtCy0LrQvtC5INGB0YLRgNC+0LrQuCDRgdGH0LjRgtCw0LXRgtGB0Y8gQVNDSUkuCm9iai50ZXh0ID0gZGIuVGV4dCgibG90cyBvZiBraXR0ZW5zIikKIyDQotC10LrRgdGC0L7QstGL0LUg0YHQstC+0LnRgdGC0LLQsCDQvNC+0LPRg9GCINGB0L7RhdGA0LDQvdGP0YLRjCDQsdC+0LvRjNGI0LjQtSDQvNCw0YHRgdC40LLRiyDQtNCw0L3QvdGL0YUuCm9iai50ZXh0ID0gZGIuVGV4dChvcGVuKCJhX3RhbGVfb2ZfdHdvX2NpdGllcy50eHQiKS5yZWFkKCksICJ1dGYtOCIpCg===

Хранилище также поддерживает работу с нетекстовыми байтовыми данными "blob" (двоичные бинарные объекты). Также как и длинные строки они не индексируются и не могут быть использованы в фильтрах запросов и их сортировках. Экземпляр класса Blob содержит массив байт и принимает в параметрах своего конструктора значение типа str. Двоичные объекты задаются с помощью класса BlobProperty.

CmNsYXNzIE15TW9kZWwoZGIuTW9kZWwpOgpibG9iID0gZGIuQmxvYlByb3BlcnR5KCkKb2JqID0gTXlNb2RlbCgpCm9iai5ibG9iID0gZGIuQmxvYihvcGVuKCJpbWFnZS5wbmciKS5yZWFkKCkpCg===

Списки

Свойство может одновременно содержать несколько значений, представленных стандартным списком языка Python типа list. Список может содержать значения любого из типов, поддерживаемых хранилищем. Свойство сохраняет порядок следования значений в списке, таким образом запросы и операция get(), вернет список в том же порядке, в каком он был сохранен.

Свойство типа ListProperty содержит список значений заданного типа. Для удобства разработчика в библиотеке также был реализован тип StringListProperty, эквивалентый конструкции ListProperty(basestring).

CmNsYXNzIE15TW9kZWwoZGIuTW9kZWwpOgpudW1iZXJzID0gZGIuTGlzdFByb3BlcnR5KGxvbmcpCm9iaiA9IE15TW9kZWwoKQpvYmoubnVtYmVycyA9IFsyLCA0LCA2LCA4LCAxMF0Kb2JqLm51bWJlcnMgPSBbImhlbGxvIl0gIyDQntCo0JjQkdCa0JA6IE15TW9kZWwubnVtYmVycyDQtNC+0LvQttC10L0g0LHRi9GC0Ywg0YHQv9C40YHQutC+0Lwg0LfQvdCw0YfQtdC90LjQuSDRgtC40L/QsCBsb25nLgo==

Использование фильтра в запросе со значением списка выполняет проверку каждого члена списка с заданным значением. Условие запроса будет выполняться в том случае, если по крайней мере одно из значений списка в объекте удовлетворяет условию.

CiMg0J/QvtC70YPRh9C40YLRjCDQstGB0LUg0L7QsdGK0LXQutGC0Ysg0YEg0L/QvtC70LXQvCBudW1iZXJzLCDRgdC+0LTQtdGA0LbQsNGJ0LjQvCA2LgpyZXN1bHRzID0gZGIuR3FsUXVlcnkoIlNFTEVDVCAqIEZST00gTXlNb2RlbCBXSEVSRSBudW1iZXJzID0gNiIpCiMg0J/QvtC70YPRh9C40YLRjCDQstGB0LUg0L7QsdGK0LXQutGC0Ysg0YEg0L/QvtC70LXQvCBudW1iZXJzLCDRgdC+0LTQtdGA0LbQsNGJ0LjQvCDQv9C+INC60YDQsNC50L3QtdC5INC80LXRgNC1INC+0LTQuNC9INGN0LvQtdC80LXQvdGCINC80LXQvdGM0YjQtSAxMC4KcmVzdWx0cyA9IGRiLkdxbFF1ZXJ5KCJTRUxFQ1QgKiBGUk9NIE15TW9kZWwgV0hFUkUgbnVtYmVycyAmbHQ7IDEwIikK=

Фильтры запросов могут работать только со значениями списков. Не существует способа сравнить два списка с помощью выполнения одного запроса.

Хранилище представляет список в своем внутреннем формате как несколько значений одного свойства. Если свойству присвоено значение, содержащее пустой список, то в хранилище оно сохранено не будет. Интерфейс Datastore API интерпретирует такие ситуации по разному в зависимости от того, являются ли списки статическими свойствами (типа ListProperty) или динамическими:

  • Статическому свойству типа ListProperty может быть присвоено значение, содержащее пустой список. Это свойство не будет помещено в хранилище, но в экземпляре модели отразится, что оно имеет пустой список. Статическое свойство типа ListProperty не может иметь значение None.
  • Динамическому свойству типа list не может быть присвоено значение пустого списка. Однако, ему может присваиваться значение None и оно может быть удалено (с использованием операции del).

Благодаря тому, что список сохраняется нестандартным способом, порядок его сортировки в запросах тоже будет особенный:

  • Если объекты сортируются по свойству со списком в порядке возрастания, то для сортировки используется значение меньшего элемента списка.
  • Если объекты сортируются по свойству со списком в порядке убывания, то для сортировки используется значение большего элемента списка.
  • Другие элементы списка никак не влияют на результат сортировки, в том числе и длина списка.
  • В случае равенства списков в качестве поля для сортировки используются ключи объектов.

Необычность этого метода сортировки выражается в том, что список [1, 9] будет расположен до списка [4, 5, 6, 7] при сортировке и по возрастанию и по убыванию.

Свойство модели ListProperty производит проверку, что в список добавляется значение корректного типа, и выдает исключение BadValueError, если это не так. Так как хранилище конвертирует все значения типа str в тип unicode с использованием кодека ascii и возвращает эти значения обратно из хранилища уже только в типе unicode, свойство ListProperty(str) работать не будет: Оно принимает от приложения сначала значения типа str, затем при обратной загрузке из хранилища происходит конвертация в тип unicode, который не совпадает с оригинальным типом, в результате чего выдается исключение BadValueError. Чтобы избежать этой проблемы используйте конструкцию ListProperty(basestring), которая допускает оба типа str и unicode, или используйте свойство StringListProperty(). Для хранения нетекстовых байтовых строк, используйте значения типа db.Blob.

Ссылки на другие объекты

Свойство может содержать ключ, ссылающийся на другой объект. Его значение должно быть экземпляром класса Key.

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

Задание экземпляра класса модели свойству типа ReferenceProperty автоматически приводит к использованию в качестве значения его ключа.

CmNsYXNzIEZpcnN0TW9kZWwoZGIuTW9kZWwpOgpwcm9wID0gZGIuSW50ZWdlclByb3BlcnR5KCkKY2xhc3MgU2Vjb25kTW9kZWwoZGIuTW9kZWwpOgpyZWZlcmVuY2UgPSBkYi5SZWZlcmVuY2VQcm9wZXJ0eShGaXJzdE1vZGVsKQpvYmoxID0gRmlyc3RNb2RlbCgpCm9iajEucHJvcCA9IDQyCm9iajEucHV0KCkKb2JqMiA9IFNlY29uZE1vZGVsKCkKIyDQn9GA0LjRgdCy0LDQuNCy0LDQtdGC0YHRjyDQt9C90LDRh9C10L3QuNC1INC60LvRjtGH0LAg0LTRgNGD0LPQvtCz0L4g0L7QsdGK0LXQutGC0LAuCm9iajIucmVmZXJlbmNlID0gb2JqMS5rZXkoKQojINCU0YDRg9Cz0L7QuSDQstCw0YDQuNCw0L3Rgjog0L/RgNC40YHQstCw0LjQstCw0L3QuNC1INGN0LrQt9C10LzQv9C70Y/RgNCwINC60LvQsNGB0YHQsCDQvNC+0LTQtdC70Lgg0LjRgdC/0L7Qu9GM0LfRg9C10YIg0LIg0LrQsNGH0LXRgdGC0LLQtSDQt9C90LDRh9C10L3QuNGPINC60LvRjtGHINGN0YLQvtCz0L4g0L7QsdGK0LXQutGC0LAuCm9iajIucmVmZXJlbmNlID0gb2JqMQo==

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

Cm9iajIucmVmZXJlbmNlLnByb3AgPSA5OTkKb2JqMi5yZWZlcmVuY2UucHV0KCkKcmVzdWx0cyA9IGRiLkdxbFF1ZXJ5KCJTRUxFQ1QgKiBGUk9NIEZpcnN0TW9kZWwiKQphbm90aGVyX29iaiA9IHJlc3VsdHMuZmV0Y2goMSlbMF0KdiA9IGFub3RoZXJfb2JqLnJlZmVyZW5jZS5wcm9wCg===

Когда объект, на который ссылается свойство другого, удаляется, последний остается неизменным. Таким образом свойство может в дальнейшем указывать на несуществующий объект. Если приложение допускает, что оно может при запросе получить ссылку на такой объект, оно должно использовать функцию db.get() и проверять ее результат до того, как будет где-то использовать этот объект.

Cm9iajEgPSBkYi5nZXQob2JqMi5yZWZlcmVuY2UpCmlmIG5vdCBvYmoxOgojINCh0YHRi9C70LDQtdC80YvQuSDQvtCx0YrQtdC60YIg0LHRi9C7INGD0LTQsNC70LXQvS4K=

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

CiMg0J/QvtC70YPRh9C40YLRjCDQuCDQvtCx0YDQsNCx0L7RgtCw0YLRjCDQutCw0LbQtNGL0Lkg0L7QsdGK0LXQutGCINGC0LjQv9CwIFNlY29uZE1vZGVsLCDQvdCwINC60L7RgtC+0YDRi9C5INGB0YHRi9C70LDQtdGC0YHRjwojINGN0LrQt9C10LzQv9C70Y/RgCDQutC70LDRgdGB0LAgRmlyc3RNb2RlbDoKZm9yIG9iaiBpbiBvYmoxLmZpcnN0bW9kZWxfc2V0OgojIC4uLgo==

Именем такого свойства с обратной ссылкой по умолчанию является модель_set (с указанным именем класса модели в нижнем регистре и строки "_set", добавленной к ней), которое может быть изменено с помощью параметра collection_name конструктора свойства ReferenceProperty.

Если в приложении вы задаете несколько значений ReferenceProperty, которые указывают на один и тот же класс модели, то они попытаются создать обратные ссылки с одним именем и произойдет ошибка:

CmNsYXNzIEZpcnN0TW9kZWwoZGIuTW9kZWwpOgpwcm9wID0gZGIuSW50ZWdlclByb3BlcnR5KCkKIyDQmtC70LDRgdGBINCy0YvQtNCw0LXRgiDQuNGB0LrQu9GO0YfQtdC90LjQtSBEdXBsaWNhdGVQcm9wZXJ0eUVycm9yINGBINGB0L7QvtCx0YnQtdC90LjQtdC8CiMgIkNsYXNzIEZpcnN0bW9kZWwgYWxyZWFkeSBoYXMgcHJvcGVydHkgc2Vjb25kbW9kZWxfc2V0IgpjbGFzcyBTZWNvbmRNb2RlbChkYi5Nb2RlbCk6CnJlZmVyZW5jZV9vbmUgPSBkYi5SZWZlcmVuY2VQcm9wZXJ0eShGaXJzdE1vZGVsKQpyZWZlcmVuY2VfdHdvID0gZGIuUmVmZXJlbmNlUHJvcGVydHkoRmlyc3RNb2RlbCkK=

Чтобы избежать этой ошибки вы должны указать параметр collection_name в конструкторе свойства:

CmNsYXNzIEZpcnN0TW9kZWwoZGIuTW9kZWwpOgpwcm9wID0gZGIuSW50ZWdlclByb3BlcnR5KCkKIyDQrdGC0L4g0L7Qv9GA0LXQtNC10LvQtdC90LjQtSDQutC70LDRgdGB0LAg0YDQsNCx0L7RgtCw0LXRggpjbGFzcyBTZWNvbmRNb2RlbChkYi5Nb2RlbCk6CnJlZmVyZW5jZV9vbmUgPSBkYi5SZWZlcmVuY2VQcm9wZXJ0eShGaXJzdE1vZGVsLApjb2xsZWN0aW9uX25hbWU9InNlY29uZG1vZGVsX3JlZmVyZW5jZV9vbmVfc2V0IikKcmVmZXJlbmNlX3R3byA9IGRiLlJlZmVyZW5jZVByb3BlcnR5KEZpcnN0TW9kZWwsCmNvbGxlY3Rpb25fbmFtZT0ic2Vjb25kbW9kZWxfcmVmZXJlbmNlX3R3b19zZXQiKQo==

Автоматическое связывание объектов, проверки типов и обратные ссылки доступны только при использовании класса свойства ReferenceProperty. Ключи, значения которых сохранены в динамических свойствах расширенных классов или свойствах типа ListProperty не обладают этими возможностями.

Названия свойств

Все названия свойств, которые начинаются и заканчиваются двумя символами подчеркивания (__*__) зарезервированы и не могут быть использованы хранилищем. Приложение не может создавать свойства с подобными именами.

В языке Python, атрибуты экземпляров модели, имена которых начинаются с символа подчеркивания (_) игнорируются и не сохраняются в хранилище. Это позволяет вам использовать такие атрибуты для временного хранения внутренних данных, не заботясь о том, что они будут сохранены вместе с объектом.

Так как Python по умолчанию использует атрибуты экземпляров класса модели для названий свойств объектов в хранилище, то в качестве них не могут использоваться имена, совпадающие с существующими методами класса модели. Аналогично, ни одно из стандартных ключевых значений, используемых в качестве параметров в конструкторе класса модели, не может быть использовано в качестве имен свойств модели. Для дополнительной информации смотрите список зарезервированных имен.

Однако, само хранилище способно использовать эти значения в качестве имен свойств данных. Если приложению требуется использовать объект хранилища, который содержит имя свойства с зарезервированным именем, то оно может воспользоваться статическим свойством и передать ключевой параметр name в качестве аргумента в конструкторе класса Property. Смотрите раздел конструктор класса Property.

CmNsYXNzIE15TW9kZWwoZGIuTW9kZWwpOgpvYmpfa2V5ID0gZGIuU3RyaW5nUHJvcGVydHkobmFtZT0ia2V5IikK=