Одно изображение стоит тысячи слов. И это является правдой, так как при взаимодействии с пользователем для сегодняшних web-приложений изображения играют большую роль. Платформа Google App Engine позволяет доступным способом оперировать изображениями и помещать их в свое хранилище. Предлагаемый интерфейс для языка Python содержит функции работы с объектами данных и построения запросов через язык GQL, собственной разработки компании Google. В этой небольшой статье я покажу, как можно использовать интерфейс Datastore API для хранения и отображения картинок, используя для примеров код приложения Movie Review.
Для начала мы хотим представить данные о каждом фильме в нашем приложении как объект хранилища. Это проще всего реализовать, определив класс модели для фильма. В классе Movie, который указан по тексту ниже, мы определяем все необходимые для описания атрибуты. Одним из них является picture, который и будет содержать двоичные данные изображения каждого фильма в формате jpeg. Для того, чтобы данные сохранялись корректно, мы должны их поместить в объект типа Blob, соответственно свойство которого будет экземпляром класса BlobProperty.
Class Movie(db.Model) title = db.StringProperty() picture = db.BlobProperty(default=None) ...
Теперь после того, как модель была определена, можно перейти к использованию ее для хранения объектов. Мы можем получить изображение фильма из удаленного источника (например, по ссылке с какого-нибудь сервера) и поместить его в наше приложение. Чтобы сделать это, воспользуемся интерфейсом URL Fetch API, который умеет загружать данные извне по URL типа HTTP и HTTPS. Метод urlfetch.Fetch() может быть использован для загрузки двоичного содержимого удаленного изображения. Для этого нам просто нужно будет указать URL изображения в качестве параметра.
Далее, создадим объект типа Blob, передав его конструктору загруженное содержимое (строковое представление бинарных данных), и присвоим полученный объект атрибуту picture экземпляру модели Movie. Затем при вызове метода put() все изменения будут помещены в хранилище.
movie = Movie() ... movie.picture = db.Blob(urlfetch.Fetch(picture_url).content) movie.put()
Теперь, когда объекты с данными фильма помещаются в наше хранилище, давайте рассмотрим пример создания обработчика, который будет динамически получать картинку из хранилища и выдавать ее в браузер пользователя.
Сначала для определения обработчика запроса типа GET мы создадим класс GetImage. Первое, что делает код этого обработчика - извлекает из URL запроса параметр title. Затем, он пытается через вызов функции getMovie() получить из хранилища объект Movie, заголовок которого будет совпадать с запросом пользователя.
Теперь мы имеем ссылку на объект и можем получить доступ к его атрибуту picture. Чтобы браузер пользователя корректно отобразил картинку, мы устанавливаем заголовку ответа HTTP Content-Type значение image/jpg.
class GetImage(webapp.RequestHandler):
def get(self):
title = self.request.get('title')
movie = getMovie(title)
if (movie and movie.picture):
self.response.headers['Content-Type'] = 'image/jpg'
self.response.out.write(movie.picture)
else:
self.redirect('/static/noimage.jpg')
Метод getMovie() содержит код, выполняющий поиск объекта с нужным заголовком с помощью простого GQL запроса к хранилищу.
def getMovie(title):
result = db.GqlQuery("SELECT * FROM Movie WHERE title = :1 LIMIT 1",
title).fetch(1)
if (len(result) > 0):
return result[0]
else:
return None
Для того, чтобы приложение вызывало наш обработчик при запросе пользователя начинающегося на URL '/image', мы должны добавить новый класс GetImage к существующей схеме URL. К примеру, для обработки GET-запросов мы используем фреймворк webapp:
apps_binding = []
...
apps_binding.append(('/image', GetImage))
application = webapp.WSGIApplication(apps_binding, debug=True)
wsgiref.handlers.CGIHandler().run(application)
Теперь, когда посетитель проследует по URL http://mydomain.com/image?title=matrix , браузер загрузит изображение фильма Матрица.
В этой статье, мы рассмотрели, как можно простым способом добавить к приложению возможность обработки и выдачи изображений из хранилища, в ответ на запрос пользователя. Теперь пришло время засучить рукава и добавить в код большей функциональности. Чтобы создать свое большое приложение, вам могут понадобиться следующие материалы: