Интерфейс Images API позволяет производить наиболее часто используемые операции по обработке изображений: изменение размера, повороты, подстройка цветности и контрастов. Все эти операции обычно выполняются при загрузке пользователем на сервер файла с изображением или фотографией. Этот документ описывает процесс загрузки, обработки, сохранения и выдачи динамических изображений. Мы будем использовать код учебного приложения 'Гостевая книга' и внесем в него изменения для того, чтобы позволить пользователям размещать их аватары вместе с сообщениями.
Первое, что необходимо сделать - обновить код модели и добавить в нее новое поле для сохранения бинарных данных изображения.
class Greeting(db.Model): author = db.UserProperty() content = db.StringProperty(multiline=True) avatar = db.BlobProperty() date = db.DateTimeProperty(auto_now_add=True)
Далее нам нужно модифицировать форму запроса данных и добавить поле для загрузки файла на сервер. Мы добавляем атрибут enctype к тэгу формы для указания того, как следует преобразовать данные формы, перед их отправкой.
self.response.out.write("""
<form action="/sign" enctype="multipart/form-data" method="post">
<div><label>Message:</label></div>
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><label>Avatar:</label></div>
<div><input type="file" name="img"/><</div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>""")
Этот код добавляет к форме два поля.
После этого необходимо обновить код обработчика приложения и добавить к нему возможность извлечения содержимого файла с изображением из запроса и сохранения его в хранилище с типом Blob.
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get("content")
avatar = self.request.get("img")
greeting.avatar = db.Blob(avatar)
greeting.put()
self.redirect('/')
Интерфейс Images API позволяет использовать несколько видов операций обработки изображений.
Вы можете изменить размер изображения и сохранить его существующие пропорции.

Вы можете перевернуть изображение на угол, кратный 90 градусам.

Вы можете зеркально перевернуть изображение по-горизонтали.

Вы можете зеркально перевернуть изображение по-вертикали.

Вы можете выполнить обрезку части изображения.

Волшебная операция "I'm Feeling Lucky" выполняет улучшение баланса цветности изображения и приводит его к оптимальным уровням.

Для нашего приложения 'Гостевая книга' мы хотим добавить поддержку пользовательских аватаров размера 32x32 пикселей. Сначала необходимо импортировать модуль google.appengine.api.images. Затем нужно вызвать функцию resize и передать ей данные изображения.
from google.appengine.api import images
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get("content")
avatar = images.resize(self.request.get("img"), 32, 32)
greeting.avatar = db.Blob(avatar)
greeting.put()
self.redirect('/')
В завершении мы создадим обработчик, который будет выдавать изображения при доступе браузера по ссылке, начинающейся на /img. Мы также обновим код, который генерирует HTML разметку и ставит ссылки на эти изображения.
class Image (webapp.RequestHandler):
def get(self):
greeting = db.get(self.request.get("img_id"))
if greeting.avatar:
self.response.headers['Content-Type'] = "image/png"
self.response.out.write(greeting.avatar)
else:
self.error(404)
Обработчик будет извлекать параметр img_id из пользовательского запроса. Теперь необходимо добавить к коду приложения передачу правильных ссылок на динамические изображения
self.response.out.write("<div><img src='img?img_id=%s'></img>" %
greeting.key())
self.response.out.write(' %s</div>' %
cgi.escape(greeting.content))
Ниже приведен полный код модифицированного приложения:
import cgi
import datetime
import wsgiref.handlers
import logging
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.api import images
logging.getLogger().setLevel(logging.DEBUG)
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
avatar = db.BlobProperty()
date = db.DateTimeProperty(auto_now_add=True)
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
query_str = "SELECT * FROM Greeting ORDER BY date DESC LIMIT 10"
greetings = db.GqlQuery (query_str)
for greeting in greetings:
if greeting.author:
self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write("<div><img src='img?img_id=%s'></img>" %
greeting.key())
self.response.out.write(' %s</div>' %
cgi.escape(greeting.content))
self.response.out.write("""
<form action="/sign" enctype="multipart/form-data" method="post">
<div><label>Message:</label></div>
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><label>Avatar:</label></div>
<div><input type="file" name="img"/></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>""")
class Image (webapp.RequestHandler):
def get(self):
greeting = db.get(self.request.get("img_id"))
if greeting.avatar:
self.response.headers['Content-Type'] = "image/png"
self.response.out.write(greeting.avatar)
else:
self.response.out.write("No image")
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get("content")
avatar = images.resize(self.request.get("img"), 32, 32)
greeting.avatar = db.Blob(avatar)
greeting.put()
self.redirect('/')
application = webapp.WSGIApplication([
('/', MainPage),
('/img', Image),
('/sign', Guestbook)
], debug=True)
def main():
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()