RU | EN

Загрузка файлов из форм в TurboGears

Иван Сагалаев рассказал как обстоят дело с загрузкой файлов через веб-формы в Django. Я решил посмотреть какая ситуация у TurboGears.
В целом все ОК, если бы не один момент. TurboGears использует FormEncode для валидации форм. FormEncode содержит FieldStorageUploadConverter для обработки полей типа FILE, вот только оно не работает. ;-) Похоже, что это просто баг - надо бы зафайлить отчет об ошибке разработчикам.
В итоге мне пришлось написать свой валидатор. Другое отличие - TurboGears не имеет специальной логики для хранения картинок/файлов. Для простоты я решил сохранить обложку в БД. Для полноты картины прилагаю и весь остальной код, готовый TG-проект можно взять здесь.
Детально комментировать мне лень, но если будет интерес можно будет написать несколько более детальных постов о TurboGears.
Так форма описывается:

class FileUploadConverter(validators.FancyValidator): def to_python(self, value, state=None): if isinstance(value, cgi.FieldStorage): if value.filename: return value raise validators.Invalid('invalid', value, state) else: return value album_form = widgets.TableForm(name='album', fields=[ widgets.TextField('title', validator=validators.UnicodeString()), widgets.FileField('cover', validator=FileUploadConverter(not_empty=False)) ])

А так - отображается (плюс показываются существующие записи):

@turbogears.expose(template='tff.templates.welcome') def index(self): albums = Album.select() return dict(albums=albums, form=album_form)

Это представление (Kid шаблон): <h2>Existing albums</h2> <p py:for="album in albums"> <img title=${album.title} alt=${album.title} py:if="album.cover" src="/get_cover?id=${album.id}" /> <span py:if="not album.cover" py:strip="True">${album.title} (no cover)</SPAN> </p> <h2>Add new album</h2> ${form.display(action=’do_add_album’)} Так происходит валидация и добавление нового альбома:

@turbogears.error_handler(index) @turbogears.validate(form=album_form) @turbogears.expose() def do_add_album(self, title=None, cover=None): if cover is not None: cover = cover.value # cover.filename contains original filename and cover.type - content-type a = Album(title=title, cover=cover) turbogears.flash('Album has been added') turbogears.redirect('/')

Ну а это - вспомогательный метод для отображения картинки на лету:

@turbogears.expose() @turbogears.validate(validators={'id':validators.Int()}) def get_cover(self, tg_errors=None, id=None): if not tg_errors: try: album = Album.get(id) content_type = 'image/gif' cherrypy.response.headers['Content-Type'] = content_type return album.cover except sqlobject.SQLObjectNotFound: pass return ''

Это собственно модель:

class Album(SQLObject): title = UnicodeCol(length=90) cover = BLOBCol()

Источники:
developers.org.ua

Автор: Ищенко М.   

Комментарии: