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

Использование хранилища

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

Благодаря Google App Engine нет необходимости задумываться об этой проблеме. Инфраструктура платформы берет на себя заботу о хранении, распределении и балансировке нагрузки обработки данных путем предоставления разработчику простого интерфейса, который позволяет выполнять запросы и производить транзакции.

Сохраняем полученные сообщения

Платформа App Engine включает в себя интерфейс API для оперирования данными на языке Python. Она похожа на модели Django, но использует для своей работы масштабируемое хранилище Google.

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

Откройте файл helloworld/helloworld.py и добавьте следующие операторы import в его начало:

CmZyb20gZ29vZ2xlLmFwcGVuZ2luZS5leHQgaW1wb3J0IGRiCg===

Добавьте следующий класс сразу после определения класса MainPage:

CmNsYXNzIEdyZWV0aW5nKGRiLk1vZGVsKToKYXV0aG9yID0gZGIuVXNlclByb3BlcnR5KCkKY29udGVudCA9IGRiLlN0cmluZ1Byb3BlcnR5KG11bHRpbGluZT1UcnVlKQpkYXRlID0gZGIuRGF0ZVRpbWVQcm9wZXJ0eShhdXRvX25vd19hZGQ9VHJ1ZSkK=

Этот код определит модель Greeting с тремя атрибутами : author со значением объекта User, content, содержащего строковые данные и date с типом datetime.datetime.

Некоторые определения атрибутов могут принимать дополнительные параметры. Указывая в конструкторе db.StringProperty параметр multiline=True, мы сообщаем, что значение в этом атрибуте может содержать символы перевода строки. Указывая в конструкторе db.DateTimeProperty параметр auto_now_add=True, мы устанавливаем, что если при создании нового объекта не будет указано значение свойства date, то ему автоматически будет присвоено значение текущего времени. Для просмотра полного списка возможных тип свойств и их опций обратитесь к руководству по интерфейсу к хранилищу.

После того, как была создана новая модель данных, приложение может ее задействовать, создав новый объект Greeting и сохранив его в хранилище. Отредактируйте обработчик Guestbook, заменив его содержимое этим кодом:

CmNsYXNzIEd1ZXN0Ym9vayh3ZWJhcHAuUmVxdWVzdEhhbmRsZXIpOgpkZWYgcG9zdChzZWxmKToKZ3JlZXRpbmcgPSBHcmVldGluZygpCmlmIHVzZXJzLmdldF9jdXJyZW50X3VzZXIoKToKZ3JlZXRpbmcuYXV0aG9yID0gdXNlcnMuZ2V0X2N1cnJlbnRfdXNlcigpCmdyZWV0aW5nLmNvbnRlbnQgPSBzZWxmLnJlcXVlc3QuZ2V0KCdjb250ZW50JykKZ3JlZXRpbmcucHV0KCkKc2VsZi5yZWRpcmVjdCgnLycpCg===

Теперь наш новый обработчик Guestbook создает объект Greeting и присваивает его атрибутам author и content данные, отправленные пользователем. Мы специально не будем устанавливать значение атрибута date, так как ранее определили, чтобы он соответствовал текущему времени при создании объекта.

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

Выполнение запросов с помощью GQL

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

Отредактируйте обработчик MainPage, заменив его код следующим:

CmNsYXNzIE1haW5QYWdlKHdlYmFwcC5SZXF1ZXN0SGFuZGxlcik6CmRlZiBnZXQoc2VsZik6CnNlbGYucmVzcG9uc2Uub3V0LndyaXRlKCcmbHQ7aHRtbCZndDsmbHQ7Ym9keSZndDsnKQpncmVldGluZ3MgPSBkYi5HcWxRdWVyeSgiU0VMRUNUICogRlJPTSBHcmVldGluZyBPUkRFUiBCWSBkYXRlIERFU0MgTElNSVQgMTAiKQpmb3IgZ3JlZXRpbmcgaW4gZ3JlZXRpbmdzOgppZiBncmVldGluZy5hdXRob3I6CnNlbGYucmVzcG9uc2Uub3V0LndyaXRlKCcmbHQ7YiZndDslcyZsdDsvYiZndDsgd3JvdGU6JyAlIGdyZWV0aW5nLmF1dGhvci5uaWNrbmFtZSgpKQplbHNlOgpzZWxmLnJlc3BvbnNlLm91dC53cml0ZSgnQW4gYW5vbnltb3VzIHBlcnNvbiB3cm90ZTonKQpzZWxmLnJlc3BvbnNlLm91dC53cml0ZSgnJmx0O2Jsb2NrcXVvdGUmZ3Q7JXMmbHQ7L2Jsb2NrcXVvdGUmZ3Q7JyAlCmNnaS5lc2NhcGUoZ3JlZXRpbmcuY29udGVudCkpCiMgV3JpdGUgdGhlIHN1Ym1pc3Npb24gZm9ybSBhbmQgdGhlIGZvb3RlciBvZiB0aGUgcGFnZQpzZWxmLnJlc3BvbnNlLm91dC53cml0ZSgiIiIKJmx0O2Zvcm0gYWN0aW9uPSIvc2lnbiIgbWV0aG9kPSJwb3N0IiZndDsKJmx0O2RpdiZndDsmbHQ7dGV4dGFyZWEgbmFtZT0iY29udGVudCIgcm93cz0iMyIgY29scz0iNjAiJmd0OyZsdDsvdGV4dGFyZWEmZ3Q7Jmx0Oy9kaXYmZ3Q7CiZsdDtkaXYmZ3Q7Jmx0O2lucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9IlNpZ24gR3Vlc3Rib29rIiZndDsmbHQ7L2RpdiZndDsKJmx0Oy9mb3JtJmd0OwombHQ7L2JvZHkmZ3Q7CiZsdDsvaHRtbCZndDsiIiIpCg===

Обновите страницу http://localhost:8080/ в своем браузере и проверьте работу, отправив несколько сообщений.

Запрос осуществляется строкой:

CmdyZWV0aW5ncyA9IGRiLkdxbFF1ZXJ5KCJTRUxFQ1QgKiBGUk9NIEdyZWV0aW5nIE9SREVSIEJZIGRhdGUgREVTQyBMSU1JVCAxMCIpCg===

Альтернативным способом вы можете вызвать метод gql(...) класса Greeting и передать параметры к стандартному запросу SELECT * FROM Greeting:

CmdyZWV0aW5ncyA9IEdyZWV0aW5nLmdxbCgiT1JERVIgQlkgZGF0ZSBERVNDIExJTUlUIDEwIikK=

Обратите внимание, что также как и в SQL ключевые слова (типа SELECT) нечувствительны к регистру. Однако, имена параметров должны быть указаны, учитывая правильный регистр.

В связи с тем, что запрос извлекает из хранилища полный набор свойств объектов, нет возможности задать выборку каких-то определенных свойств. GQL запросы всегда начинаются со значения SELECT * FROM модель (или также подразумеваются методом gql(...) модели) и этим напоминают свои эквиванеты в SQL.

GQL запрос может содержать условие WHERE, которое произведет отбор результатов через заданный фильтр. В отличии от SQL, запросы GQL не обязательно должны содержать в своих параметрах константы, к ним можно привязывать любое значение. К примеру, можно отобразить только сообщения, отправленные текущим пользователем:

CmlmIHVzZXJzLmdldF9jdXJyZW50X3VzZXIoKToKZ3JlZXRpbmdzID0gR3JlZXRpbmcuZ3FsKCJXSEVSRSBhdXRob3IgPSA6MSBPUkRFUiBCWSBkYXRlIERFU0MiLAp1c2Vycy5nZXRfY3VycmVudF91c2VyKCkpCg===

Вместо именованных параметров также можно использовать позиционные:

CmdyZWV0aW5ncyA9IEdyZWV0aW5nLmdxbCgiV0hFUkUgYXV0aG9yID0gOmF1dGhvciBPUkRFUiBCWSBkYXRlIERFU0MiLAphdXRob3I9dXNlcnMuZ2V0X2N1cnJlbnRfdXNlcigpKQo==

В дополнении к языку запросов GQL, интерфейс к хранилищу данных предоставляет еще один механизм построения запросов через использование методов. Например, запрос может быть подготовлен следущим кодом:

CmdyZWV0aW5ncyA9IEdyZWV0aW5nLmFsbCgpCmdyZWV0aW5ncy5maWx0ZXIoImF1dGhvciA9IiwgdXNlcnMuZ2V0X2N1cnJlbnRfdXNlcigpKQpncmVldGluZ3Mub3JkZXIoIi1kYXRlIikK=

Для просмотра полного описания возможностей GQL и интерфейса доступа к данным обратитесь к руководству по работе с хранилищем.

Очистка локального хранилища

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

Если появится необходимость перед выполнением приложения удалить данные хранилища, воспользуйтесь параметром --clear_datastore при запуске локального сервера:

ZGV2X2FwcHNlcnZlci5weSAtLWNsZWFyX2RhdGFzdG9yZSBoZWxsb3dvcmxkLwo==

Далее...

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

Наша последняя версия смешивает в обработчике MainPage код приложения вместе с содержимым HTML. Это не позволяет быстро изменять внешний вид приложения, что особенно станет заметным при увеличении его сложности и объема. Мы сможем задействовать механизм шаблонов для управления содержанием и поместить стили CSS в отдельные статические файлы.

Перейти к Использование шаблонов.