Разработка web-приложений с repoze.bfg

57
Разработка web-приложений с repoze.bfg Андрей Попп [email protected] http://braintrace.ru @andreypopp

Transcript of Разработка web-приложений с repoze.bfg

Page 1: Разработка web-приложений с repoze.bfg

Разработка web-приложений с repoze.bfg

Андрей Попп

[email protected]

http://braintrace.ru

@andreypopp

Page 2: Разработка web-приложений с repoze.bfg

Что такое repoze.bfg

Это минималистичный web-фрэймворк, вобравший в себя идеиZope, Django, Pylons.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 3: Разработка web-приложений с repoze.bfg

Что такое repoze.bfg

Ключевые моменты:

WSGI.MVC (скорее даже MTV).Компонентная архитектура.100% покрытие тестами (по отчётам утилиты Coverage).Отличная документация.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 4: Разработка web-приложений с repoze.bfg

Что такое repoze.bfg

Фрэймворк предоставляет инструменты, помогающие решениюследующих проблем:

Конфигурация приложения.Маршрутизация запросов.Шаблонизация.Аутентификация и авторизация.Интернационализация и локализация.Тестирование приложения.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 5: Разработка web-приложений с repoze.bfg

Что такое repoze.bfg

Остальное вопросы остаются за разработчиком:

Где и как хранятся данные приложения.Как генерировать и обрабатывать формы.Где хранить данные сессии.Кэширование.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 6: Разработка web-приложений с repoze.bfg

Что такое repoze.bfg

Repoze.bfg использует хорошо знакомые и проверенныетехнологии:

WebOb/Paste – уровень WSGI.ZCA/ZCML – компонентная архитектура и конфигурация.Babel – интернационализация и локализация.Zope Page Templates – система шаблонизации.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 7: Разработка web-приложений с repoze.bfg

Неужели repoze.bfg использует библиотеки Zope?!

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 8: Разработка web-приложений с repoze.bfg

Использование Zope библиотек

Да, repoze.bfg использует Zope библиотеки, но:

Их использование – это просто деталь реализациифрэймворка.Пользователь фрэймворка не обязан знать и использоватьбиблиотеки Zope.Библиотеки Zope не так уж плохи.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 9: Разработка web-приложений с repoze.bfg

Начинаем работать с repoze.bfg

Чтобы создать проект repoze.bfg, можно воспользоватьсяодним из шаблонов Paste:

paster create -t <template_name > <project_name >

Шаблонов всего три: bfg_starter, bfg_zodb, bfg_alchemy,bfg_routesalchemy, но об этом позже.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 10: Разработка web-приложений с repoze.bfg

Начинаем работать с repoze.bfg

В результате получаем готовую структуру пакета подуправлением setuptools (или distribute).

Приложение уже настроено для запуска с помощью Paste:

paster serve paste.ini --reload

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 11: Разработка web-приложений с repoze.bfg

Конфигурация приложения

Конфигурация приложения это:

URL приложения и как они отображаются напредставления.Статические ресурсы и используемые шаблоны.Политики аутентификации и авторизации.Файлы с локализацией.Компоненты, специфичные для приложения.

Почти как settings.py и urls.py в Django.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 12: Разработка web-приложений с repoze.bfg

Конфигурация приложения

Конфигурацию приложения не стоит путать с настройкамиприложения.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 13: Разработка web-приложений с repoze.bfg

Конфигурация приложения

Конфигурация выполняется с помощью объекта Configurator:

Императивно – c помощью вызововConfigurator.add_route, Configurator.add_view и т.д.Декларативно – с помощью ZCML.С помощью декораторов.

После выполнения конфигурации необходимо вызвать методConfigurator.make_wsgi_app(), чтобы создатьсконфигурированное WSGI приложение.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 14: Разработка web-приложений с repoze.bfg

Конфигурация приложенияПример: императивная конфигурация

myproject/run.py:

...config = Configurator ()config.begin()config.add_view(views.show_entries)config.add_view(views.show_comments)config.end()wsgi_app = config.make_wsgi_app ()...

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 15: Разработка web-приложений с repoze.bfg

Конфигурация приложенияПример: конфигурация с помощью декораторов

myproject/run.py:

...config = Configurator ()config.begin()config.scan()config.end()wsgi_app = config.make_wsgi_app ()...

myproject/views.py:

...@bfg_view ()def show_entries(request ):

return Response ()...

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 16: Разработка web-приложений с repoze.bfg

Конфигурация приложенияПример: декларативная конфигурация с помощью ZCML

myproject/run.py:

...config = Configurator ()config.begin()config.load_zcml(’configure.zcml ’)config.end()wsgi_app = config.make_wsgi_app ()...

myproject/configure.zcml:

...<view view=" myproject.views.show_entries"><view view=" myproject.views.show_comments">...

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 17: Разработка web-приложений с repoze.bfg

Конфигурация приложения

Все три приведённых примера абсолютно идентичны в планеконечного результата.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 18: Разработка web-приложений с repoze.bfg

Конфигурация приложения

Но использование ZCML позволяет разрабатыватьрасширяемые приложения.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 19: Разработка web-приложений с repoze.bfg

Конфигурация приложенияЧто такое ZCML

ZCML (Zope Configuration Markup Language) – декларативный,основанный на XML, язык для описания конфигураций.

Для repoze.bfg cуществует набор директив ZCML (таких какview), которые потом преобразуются в вызовы функций (вслучае с view – в вызов метода Configuration.add_view).

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 20: Разработка web-приложений с repoze.bfg

Конфигурация приложенияДиректива ZCML – include

С помощью директивы include можно подгружатьконфигурацию из других ZCML файлов других пакетов:

...<include package =" anotherproject" /><include package =" yetanotherproject" />...

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

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 21: Разработка web-приложений с repoze.bfg

Конфигурация приложения

Преобразование директив конфигурации в вызовы функцийпроизводится только после считывания всех необходимых

файлов конфигурации.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 22: Разработка web-приложений с repoze.bfg

Конфигурация приложения

Именно потому, что с ZCML возможно переопределятьконфигурацию приложения, его необходимо использовать для

разработки расширяемых приложений.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 23: Разработка web-приложений с repoze.bfg

Конфигурация приложенияПример организации ZCML конфигурации в приложении

Обычно экземпляр установленного приложения содержитследующую ZCML конфигурацию:

...<include package =" myproject.core" /><include package =" myproject.additional_module" />...

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 24: Разработка web-приложений с repoze.bfg

Конфигурация приложенияПример организации ZCML конфигурации в приложении

Если нам нужно добавить ещё функционала в приложение:

...<include package =" myproject.core" /><include package =" myproject.additional_module" /><include package="myproject.plugins.openid"/>...

Мы просто подключаем конфигурацию пакета, которыйпредоставляет нужный функционал.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 25: Разработка web-приложений с repoze.bfg

Поговорим о представлениях в repoze.bfg.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 26: Разработка web-приложений с repoze.bfg

Представления в repoze.bfg

Представлением может служить, как функция вида

def my_view(request ):return Response(’Hello , world!’)

так и класс с методом __call__

class MyView(object ):def __init__(self , request ):

passdef __call__(self):

return Response(’Hello , world!’)

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 27: Разработка web-приложений с repoze.bfg

Представления в repoze.bfg

Аргумент request – это объект WebOb.Request.

Представление должно возвращать объект с атрибутами:

status – строка HTTP статуса.headerlist – список HTTP заголовков.app_iter – итератор по телу ответа.

Таким объектом, например, является WebOb.Response.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 28: Разработка web-приложений с repoze.bfg

Представления в repoze.bfg

Кроме того, представление может зависеть от контекста

def my_view(context, request ):return Response(’Hello , world!’)

или

class MyView(object ):def __init__(self , context, request ):

passdef __call__(self):

return Response(’Hello , world!’)

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 29: Разработка web-приложений с repoze.bfg

Представления в repoze.bfg

Контекст представления – это объект из предметной областиприложения.

Для каждого запроса он определяется с помощью механизманахождения контекста, но об этом позже.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 30: Разработка web-приложений с repoze.bfg

Представления в repoze.bfg

Почему хорошо иметь в приложении контекстно-зависимыепредставления:

Для разных типов контекста можно определять разныепредставления.Можно устанавливать ограничения на представления взависимости от контекста.

Но использование контекстно-зависимых представлений вприложении полностью опционально, если хочется – можноделать как в Django, Pylons. . .

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 31: Разработка web-приложений с repoze.bfg

Как происходит маршрутизация запросов в repoze.bfg или какURL запроса отображается на представление?

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 32: Разработка web-приложений с repoze.bfg

Маршрутизация запросов

Весь процесс маршрутизации запроса происходит в две фазы:

Нахождение контекста для запроса.Выбор представления для запроса и найденного контекста.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 33: Разработка web-приложений с repoze.bfg

Маршрутизация запросов

Существует три способа организовать маршрутизациюзапросов в приложении:

Нахождение контекста с помощью обхода графа объектови последующий выбор представления.Сопоставление URL запроса с шаблонами, контекстуказывается явно для шаблона URL.Гибридный способ – сначала идёт сопоставление с нужнымURL-шаблоном, а потом обход графа объектов.

Аналогично первому способу работает Zope, второй способхарактерен для Django, Pylons и т.п.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 34: Разработка web-приложений с repoze.bfg

Маршрутизация запросовОбход графа

Удобно использовать, когда:

Множество объектов предметной области имеет структуруграфа.URL приложения можно интерпретировать как пути в этомграфе.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 35: Разработка web-приложений с repoze.bfg

Маршрутизация запросовОбход графа

Обход графа начинается с корневого объекта.

Фабрика для создания корневого объекта указывается на этапеконфигурации:

config = Configurator(root_factory=some_factory , ...)

Где some_factory – это функция, которая принимает requestединственным аргументом и возвращает корневой объект.

def some_factory(request ):return RootObject ()

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 36: Разработка web-приложений с repoze.bfg

Маршрутизация запросовОбход графа

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

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 37: Разработка web-приложений с repoze.bfg

Маршрутизация запросовОбход графа

Допустим, что мы проектируем приложение для управлениястатическими страницами.

Кроме корневого объекта RootObject, у нас есть следующиеобъекты предметной области:

Объект PageManager – это менеджер статических страниц,через него мы можем получить нужную страницу по еёидентификатору.Объект Page – представляет отдельную страницу.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 38: Разработка web-приложений с repoze.bfg

Маршрутизация запросовОбход графа

Как происходит обход графа на примере URL /pages/page1:

1 URL разбивается на части: [’pages’, ’page1’].2 Вызывается метод RootObject.__getitem__ с аргументом

’pages’. Этот метод возвращает объект PageManager.3 Вызывается метод PageManager.__getitem__ с

аргументом ’page1’. В результате получаем объект Page.

Так как частей URL у нас больше не осталось, найденныйобъект Page является контекстом данного запроса.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 39: Разработка web-приложений с repoze.bfg

Маршрутизация запросовВыбор представления

После того, как мы нашли контекст, нам нужно выбратьподходящее представление.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 40: Разработка web-приложений с repoze.bfg

Маршрутизация запросовВыбор представления

Представления для объектов предметной областиопределяются на этапе конфигурации.

Императивно:

config.add_view(show_page , for_=Page)config.add_view(show_comment , for_=Comment)

или с помощью ZCML:

<view view=" views.show_page" for=" models.Page" /><view view=" views.show_comment" for=" models.Comment" />

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 41: Разработка web-приложений с repoze.bfg

Маршрутизация запросовВыбор представления

Выбор представления учитывает Method Resolution Order.

Если не найдено представления для конкретного типа, будетиспользовано представление для его супертипа.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 42: Разработка web-приложений с repoze.bfg

Маршрутизация запросовВыбор представления

Кроме этого, можно определять разные представления дляразных HTTP методов, разных значений HTTP заголовков и на

основе других предикатов.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 43: Разработка web-приложений с repoze.bfg

Маршрутизация запросовШаблоны URL

Если маршрутизация запросов с помощью обхода графа неподходит, можно использовать сопоставление URL с

шаблонами.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 44: Разработка web-приложений с repoze.bfg

Маршрутизация запросовШаблоны URL

Механизм сопоставления URL с шаблонами работает также,как и в Django, Routes и т.д.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 45: Разработка web-приложений с repoze.bfg

Маршрутизация запросовШаблоны URL

Шаблоны URL приложения определяются на этапеконфигурации.

Императивно:

config.add_route(view=show_page ,path ="/ pages/: page_id")

или с помощью ZCML:

<routeview="views.show_page"path ="/p/: page_id"/>

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 46: Разработка web-приложений с repoze.bfg

Маршрутизация запросовШаблоны URL

Контекст указывается явно:

config.add_route(view=show_page ,path ="/ pages/: page_id",factory=" some_factory")

или с помощью ZCML:

<routeview="views.show_page"path ="/p/: page_id"factory=" some_factory"/>

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 47: Разработка web-приложений с repoze.bfg

Маршрутизация запросовШаблоны URL

Для каждого шаблона можно определить несколькопредставлений для разных типов контекста:

<routename="pages"path ="/p/: page_id"factory =" some_factory"/>

<viewroute_name ="pages"for="Page"/>

<viewroute_name ="pages"for=" MainPage"/>

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 48: Разработка web-приложений с repoze.bfg

Маршрутизация запросовГибридный метод

Можно комбинировать обход графа и шаблоны URL:

<routename="pages"path ="/ pages/: category_id /* traverse"factory =" some_factory"/>

В этом случае первая URL сначала будет сопоставляться с/pages/:category_id, а оставшаяся часть будетиспользоована для обхода графа объектов начиная с объекта,произведённого с some_factory.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 49: Разработка web-приложений с repoze.bfg

Маршрутизация запросовОбработка исключений

Что происходит, если во время выполнения представленияпроисходит исключение?

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 50: Разработка web-приложений с repoze.bfg

Маршрутизация запросовОбработка исключений

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

Представления для исключений регистрируются обычнымобразом:

<viewfor=" webob.exc.HTTPNotFound"view=" notfound_view"/>

Если во время исполнения любого представления произойдётисключение webob.exc.HTTPNotFound, то исполнение перейдётк notfound_view.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 51: Разработка web-приложений с repoze.bfg

Шаблонизация

По-умолчанию, repoze.bfg предлагает использоватьшаблонизатор Chameleon – это реализация Zope Page

Templates и Genshi.

Кроме того, на pypi присутствует пакет repoze.bfg.jinja2 – дляработы с шаблонизатором Jinja2.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 52: Разработка web-приложений с repoze.bfg

Шаблонизация

Как уже упоминалось, представление должно возращатьобъект с интерфейсом Response.

Это не всегда удобно, особенно когда дело касаетсятестирования, а представление рендерит тяжёлый шаблон:

response = myview(request)assert ’Some text ’ in ’’.join(response.app_iter)

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 53: Разработка web-приложений с repoze.bfg

Шаблонизация

Repoze.bfg предлагает следующее решение:

Представления возвращает dict() объект.За преобразование этого объекта в конечный Responseответственнен отдельный объект – рендерер.Рендерер определяется для каждого представления наэтапе конфигурации.Шаблоны являются рендерерами.

<viewview="views.some_pages"renderer =" list_pages.jinja2"/>

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 54: Разработка web-приложений с repoze.bfg

Шаблонизация

В repoze.bfg по-умолчанию присутствуют рендереры длявывода JSON и ZPT шаблонов.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 55: Разработка web-приложений с repoze.bfg

Шаблонизация

Пакет repoze.bfg.jinja2 предоставляет рендерер для шаблоновJinja2.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 56: Разработка web-приложений с repoze.bfg

Заключение

На этом всё. Читайте документацию –http://docs.repoze.org/bfg/.

Андрей Попп: Разработка web-приложений с repoze.bfg

Page 57: Разработка web-приложений с repoze.bfg

Спасибо! Вопросы?

Андрей Попп: Разработка web-приложений с repoze.bfg