SlideShare a Scribd company logo
1 of 57
Download to read offline
Разработка web-приложений с repoze.bfg


                       Андрей Попп




8mayday@gmail.com

http://braintrace.ru

@andreypopp
Что такое repoze.bfg




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




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



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

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




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


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

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




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




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

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




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



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

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




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




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



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

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




Андрей Попп: Разработка 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
Начинаем работать с repoze.bfg




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

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

       paster serve paste . ini -- reload




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


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

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

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



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




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




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


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

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

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




Андрей Попп: Разработка 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
Конфигурация приложения
 Пример: конфигурация с помощью декораторов

      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
Конфигурация приложения
 Пример: декларативная конфигурация с помощью 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
Конфигурация приложения




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




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




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




Андрей Попп: Разработка web-приложений с repoze.bfg
Конфигурация приложения
 Что такое ZCML




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

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




Андрей Попп: Разработка web-приложений с repoze.bfg
Конфигурация приложения
 Директива ZCML – include




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

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



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



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




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




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




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




Андрей Попп: Разработка web-приложений с repoze.bfg
Конфигурация приложения
 Пример организации ZCML конфигурации в приложении




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

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




Андрей Попп: Разработка web-приложений с repoze.bfg
Конфигурация приложения
 Пример организации ZCML конфигурации в приложении




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

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



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




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




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


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

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



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

       class MyView ( object ):
           def __init__ ( self , request ):
               pass
           def __call__ ( self ):
               return Response ( ’ Hello , world ! ’)




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



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

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

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

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




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


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

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



      или

       class MyView ( object ):
           def __init__ ( self , context, request ):
               pass
           def __call__ ( self ):
               return Response ( ’ Hello , world ! ’)




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




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

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




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


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

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

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



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




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




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

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




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

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

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

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


Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Обход графа




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

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




Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Обход графа



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

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

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



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

       def some_factory ( request ):
           return RootObject ()




Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Обход графа




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




Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Обход графа




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

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

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




Андрей Попп: Разработка 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
Маршрутизация запросов
 Выбор представления




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




Андрей Попп: Разработка 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
Маршрутизация запросов
 Выбор представления




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

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




Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Выбор представления




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




Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Шаблоны URL




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




Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Шаблоны URL




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




Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Шаблоны URL

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

      Императивно:
       config . add_route (
           view = show_page ,
           path ="/ pages /: page_id "
           )



      или с помощью ZCML:
       < route
            view =" views . show_page "
            path ="/ p /: page_id "
            />

Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Шаблоны URL


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

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



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

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


Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Шаблоны URL

      Для каждого шаблона можно определить несколько
      представлений для разных типов контекста:
       < route
            name =" pages "
            path ="/ p /: page_id "
            factory =" some_factory "
            />

       < view
            route_name =" pages "
            for =" Page "
            />

       < view
            route_name =" pages "
            for =" MainPage "
            />

Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Гибридный метод



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

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



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



Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Обработка исключений




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




Андрей Попп: Разработка web-приложений с repoze.bfg
Маршрутизация запросов
 Обработка исключений


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

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

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



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

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




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

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




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



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

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

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




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

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

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

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



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




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




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




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




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




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




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




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

More Related Content

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

Лекция #6. Введение в Django web-framework
Лекция #6. Введение в Django web-frameworkЛекция #6. Введение в Django web-framework
Лекция #6. Введение в Django web-frameworkЯковенко Кирилл
 
Устройство фреймворка symfony 2 (http://frontend-dev.ru)
Устройство фреймворка symfony 2 (http://frontend-dev.ru)Устройство фреймворка symfony 2 (http://frontend-dev.ru)
Устройство фреймворка symfony 2 (http://frontend-dev.ru)Александр Егурцов
 
Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)
Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)
Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)7bits
 
Денис Паясь
Денис ПаясьДенис Паясь
Денис ПаясьCodeFest
 
Современный фронтенд за 30 минут.
Современный фронтенд за 30 минут.Современный фронтенд за 30 минут.
Современный фронтенд за 30 минут.Vladimir Malyk
 
Как быть с большими сайтами на Word press
Как быть с большими сайтами  на Word pressКак быть с большими сайтами  на Word press
Как быть с большими сайтами на Word pressvovasik
 
Создаем Drupal дистрибутив: от идеи до сопровождения
Создаем Drupal дистрибутив: от идеи до сопровожденияСоздаем Drupal дистрибутив: от идеи до сопровождения
Создаем Drupal дистрибутив: от идеи до сопровожденияOvadiah Myrgorod
 
Любовь Поволоцкая_Сборка Android-приложений с помощью Gradle
Любовь Поволоцкая_Сборка Android-приложений с помощью GradleЛюбовь Поволоцкая_Сборка Android-приложений с помощью Gradle
Любовь Поволоцкая_Сборка Android-приложений с помощью GradleGeeksLab Odessa
 
Деплоймент и распространение обновлений для веб-приложений
Деплоймент и распространение обновлений для веб-приложенийДеплоймент и распространение обновлений для веб-приложений
Деплоймент и распространение обновлений для веб-приложенийMagecom Ukraine
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.Igor Shkulipa
 
управление сборками и развертыванием веб приложений
управление сборками и развертыванием веб приложенийуправление сборками и развертыванием веб приложений
управление сборками и развертыванием веб приложенийSergii Shmarkatiuk
 
The Old New ASP.NET
The Old New ASP.NETThe Old New ASP.NET
The Old New ASP.NETVitaly Baum
 
[JAM 1.1] Symfony (Alexei Yanochkin)
[JAM 1.1] Symfony (Alexei Yanochkin)[JAM 1.1] Symfony (Alexei Yanochkin)
[JAM 1.1] Symfony (Alexei Yanochkin)Evgeny Kaziak
 
Использование Symfony
Использование SymfonyИспользование Symfony
Использование SymfonyMedia Gorod
 
Protrarctor and Angular
Protrarctor and AngularProtrarctor and Angular
Protrarctor and AngularSQALab
 
Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальBadoo Development
 
C# Web. Занятие 13.
C# Web. Занятие 13.C# Web. Занятие 13.
C# Web. Занятие 13.Igor Shkulipa
 

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

Лекция #6. Введение в Django web-framework
Лекция #6. Введение в Django web-frameworkЛекция #6. Введение в Django web-framework
Лекция #6. Введение в Django web-framework
 
Backbone Javascript Application
Backbone Javascript ApplicationBackbone Javascript Application
Backbone Javascript Application
 
Устройство фреймворка symfony 2 (http://frontend-dev.ru)
Устройство фреймворка symfony 2 (http://frontend-dev.ru)Устройство фреймворка symfony 2 (http://frontend-dev.ru)
Устройство фреймворка symfony 2 (http://frontend-dev.ru)
 
Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)
Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)
Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)
 
Денис Паясь
Денис ПаясьДенис Паясь
Денис Паясь
 
Современный фронтенд за 30 минут.
Современный фронтенд за 30 минут.Современный фронтенд за 30 минут.
Современный фронтенд за 30 минут.
 
Как быть с большими сайтами на Word press
Как быть с большими сайтами  на Word pressКак быть с большими сайтами  на Word press
Как быть с большими сайтами на Word press
 
Backbone lesson 1
Backbone lesson 1Backbone lesson 1
Backbone lesson 1
 
Создаем Drupal дистрибутив: от идеи до сопровождения
Создаем Drupal дистрибутив: от идеи до сопровожденияСоздаем Drupal дистрибутив: от идеи до сопровождения
Создаем Drupal дистрибутив: от идеи до сопровождения
 
Любовь Поволоцкая_Сборка Android-приложений с помощью Gradle
Любовь Поволоцкая_Сборка Android-приложений с помощью GradleЛюбовь Поволоцкая_Сборка Android-приложений с помощью Gradle
Любовь Поволоцкая_Сборка Android-приложений с помощью Gradle
 
Деплоймент и распространение обновлений для веб-приложений
Деплоймент и распространение обновлений для веб-приложенийДеплоймент и распространение обновлений для веб-приложений
Деплоймент и распространение обновлений для веб-приложений
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.
 
управление сборками и развертыванием веб приложений
управление сборками и развертыванием веб приложенийуправление сборками и развертыванием веб приложений
управление сборками и развертыванием веб приложений
 
The Old New ASP.NET
The Old New ASP.NETThe Old New ASP.NET
The Old New ASP.NET
 
[JAM 1.1] Symfony (Alexei Yanochkin)
[JAM 1.1] Symfony (Alexei Yanochkin)[JAM 1.1] Symfony (Alexei Yanochkin)
[JAM 1.1] Symfony (Alexei Yanochkin)
 
RichFaces: обзор
RichFaces: обзорRichFaces: обзор
RichFaces: обзор
 
Использование Symfony
Использование SymfonyИспользование Symfony
Использование Symfony
 
Protrarctor and Angular
Protrarctor and AngularProtrarctor and Angular
Protrarctor and Angular
 
Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон Довгаль
 
C# Web. Занятие 13.
C# Web. Занятие 13.C# Web. Занятие 13.
C# Web. Занятие 13.
 

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

  • 1. Разработка web-приложений с repoze.bfg Андрей Попп 8mayday@gmail.com http://braintrace.ru @andreypopp
  • 2. Что такое repoze.bfg Это минималистичный web-фрэймворк, вобравший в себя идеи Zope, Django, Pylons. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 3. Что такое repoze.bfg Ключевые моменты: WSGI. MVC (скорее даже MTV). Компонентная архитектура. 100% покрытие тестами (по отчётам утилиты Coverage). Отличная документация. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 4. Что такое repoze.bfg Фрэймворк предоставляет инструменты, помогающие решению следующих проблем: Конфигурация приложения. Маршрутизация запросов. Шаблонизация. Аутентификация и авторизация. Интернационализация и локализация. Тестирование приложения. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 5. Что такое repoze.bfg Остальное вопросы остаются за разработчиком: Где и как хранятся данные приложения. Как генерировать и обрабатывать формы. Где хранить данные сессии. Кэширование. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 6. Что такое repoze.bfg Repoze.bfg использует хорошо знакомые и проверенные технологии: WebOb/Paste – уровень WSGI. ZCA/ZCML – компонентная архитектура и конфигурация. Babel – интернационализация и локализация. Zope Page Templates – система шаблонизации. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 7. Неужели repoze.bfg использует библиотеки Zope?! Андрей Попп: Разработка web-приложений с repoze.bfg
  • 8. Использование Zope библиотек Да, repoze.bfg использует Zope библиотеки, но: Их использование – это просто деталь реализации фрэймворка. Пользователь фрэймворка не обязан знать и использовать библиотеки Zope. Библиотеки Zope не так уж плохи. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 9. Начинаем работать с repoze.bfg Чтобы создать проект repoze.bfg, можно воспользоваться одним из шаблонов Paste: paster create -t < template_name > < project_name > Шаблонов всего три: bfg_starter, bfg_zodb, bfg_alchemy, bfg_routesalchemy, но об этом позже. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 10. Начинаем работать с repoze.bfg В результате получаем готовую структуру пакета под управлением setuptools (или distribute). Приложение уже настроено для запуска с помощью Paste: paster serve paste . ini -- reload Андрей Попп: Разработка web-приложений с repoze.bfg
  • 11. Конфигурация приложения Конфигурация приложения это: URL приложения и как они отображаются на представления. Статические ресурсы и используемые шаблоны. Политики аутентификации и авторизации. Файлы с локализацией. Компоненты, специфичные для приложения. Почти как settings.py и urls.py в Django. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 12. Конфигурация приложения Конфигурацию приложения не стоит путать с настройками приложения. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 13. Конфигурация приложения Конфигурация выполняется с помощью объекта Configurator: Императивно – c помощью вызовов Configurator.add_route, Configurator.add_view и т.д. Декларативно – с помощью ZCML. С помощью декораторов. После выполнения конфигурации необходимо вызвать метод Configurator.make_wsgi_app(), чтобы создать сконфигурированное WSGI приложение. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 14. Конфигурация приложения Пример: императивная конфигурация 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
  • 15. Конфигурация приложения Пример: конфигурация с помощью декораторов 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
  • 16. Конфигурация приложения Пример: декларативная конфигурация с помощью 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
  • 17. Конфигурация приложения Все три приведённых примера абсолютно идентичны в плане конечного результата. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 18. Конфигурация приложения Но использование ZCML позволяет разрабатывать расширяемые приложения. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 19. Конфигурация приложения Что такое ZCML ZCML (Zope Configuration Markup Language) – декларативный, основанный на XML, язык для описания конфигураций. Для repoze.bfg cуществует набор директив ZCML (таких как view), которые потом преобразуются в вызовы функций (в случае с view – в вызов метода Configuration.add_view). Андрей Попп: Разработка web-приложений с repoze.bfg
  • 20. Конфигурация приложения Директива ZCML – include С помощью директивы include можно подгружать конфигурацию из других ZCML файлов других пакетов: ... < include package =" anotherproject " / > < include package =" yetanotherproject " / > ... Порядок таких включений имеет значение, потому что директивы, встречающиеся в файлах конфигурации могут переопределять друг друга. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 21. Конфигурация приложения Преобразование директив конфигурации в вызовы функций производится только после считывания всех необходимых файлов конфигурации. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 22. Конфигурация приложения Именно потому, что с ZCML возможно переопределять конфигурацию приложения, его необходимо использовать для разработки расширяемых приложений. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 23. Конфигурация приложения Пример организации ZCML конфигурации в приложении Обычно экземпляр установленного приложения содержит следующую ZCML конфигурацию: ... < include package =" myproject . core " / > < include package =" myproject . additional_module " / > ... Андрей Попп: Разработка web-приложений с repoze.bfg
  • 24. Конфигурация приложения Пример организации ZCML конфигурации в приложении Если нам нужно добавить ещё функционала в приложение: ... < include package =" myproject . core " / > < include package =" myproject . additional_module " / > <include package="myproject.plugins.openid"/> ... Мы просто подключаем конфигурацию пакета, который предоставляет нужный функционал. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 25. Поговорим о представлениях в repoze.bfg. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 26. Представления в repoze.bfg Представлением может служить, как функция вида def my_view ( request ): return Response ( ’ Hello , world ! ’) так и класс с методом __call__ class MyView ( object ): def __init__ ( self , request ): pass def __call__ ( self ): return Response ( ’ Hello , world ! ’) Андрей Попп: Разработка web-приложений с repoze.bfg
  • 27. Представления в repoze.bfg Аргумент request – это объект WebOb.Request. Представление должно возвращать объект с атрибутами: status – строка HTTP статуса. headerlist – список HTTP заголовков. app_iter – итератор по телу ответа. Таким объектом, например, является WebOb.Response. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 28. Представления в repoze.bfg Кроме того, представление может зависеть от контекста def my_view (context, request ): return Response ( ’ Hello , world ! ’) или class MyView ( object ): def __init__ ( self , context, request ): pass def __call__ ( self ): return Response ( ’ Hello , world ! ’) Андрей Попп: Разработка web-приложений с repoze.bfg
  • 29. Представления в repoze.bfg Контекст представления – это объект из предметной области приложения. Для каждого запроса он определяется с помощью механизма нахождения контекста, но об этом позже. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 30. Представления в repoze.bfg Почему хорошо иметь в приложении контекстно-зависимые представления: Для разных типов контекста можно определять разные представления. Можно устанавливать ограничения на представления в зависимости от контекста. Но использование контекстно-зависимых представлений в приложении полностью опционально, если хочется – можно делать как в Django, Pylons. . . Андрей Попп: Разработка web-приложений с repoze.bfg
  • 31. Как происходит маршрутизация запросов в repoze.bfg или как URL запроса отображается на представление? Андрей Попп: Разработка web-приложений с repoze.bfg
  • 32. Маршрутизация запросов Весь процесс маршрутизации запроса происходит в две фазы: Нахождение контекста для запроса. Выбор представления для запроса и найденного контекста. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 33. Маршрутизация запросов Существует три способа организовать маршрутизацию запросов в приложении: Нахождение контекста с помощью обхода графа объектов и последующий выбор представления. Сопоставление URL запроса с шаблонами, контекст указывается явно для шаблона URL. Гибридный способ – сначала идёт сопоставление с нужным URL-шаблоном, а потом обход графа объектов. Аналогично первому способу работает Zope, второй способ характерен для Django, Pylons и т.п. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 34. Маршрутизация запросов Обход графа Удобно использовать, когда: Множество объектов предметной области имеет структуру графа. URL приложения можно интерпретировать как пути в этом графе. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 35. Маршрутизация запросов Обход графа Обход графа начинается с корневого объекта. Фабрика для создания корневого объекта указывается на этапе конфигурации: config = Configurator ( root_factory = some_factory , ...) Где some_factory – это функция, которая принимает request единственным аргументом и возвращает корневой объект. def some_factory ( request ): return RootObject () Андрей Попп: Разработка web-приложений с repoze.bfg
  • 36. Маршрутизация запросов Обход графа Обычно, в качестве корневого объекта используется интерфейс к БД или любому другому механизму хранения данных. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 37. Маршрутизация запросов Обход графа Допустим, что мы проектируем приложение для управления статическими страницами. Кроме корневого объекта RootObject, у нас есть следующие объекты предметной области: Объект PageManager – это менеджер статических страниц, через него мы можем получить нужную страницу по её идентификатору. Объект Page – представляет отдельную страницу. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 38. Маршрутизация запросов Обход графа Как происходит обход графа на примере URL /pages/page1: 1 URL разбивается на части: [’pages’, ’page1’]. 2 Вызывается метод RootObject.__getitem__ с аргументом ’pages’. Этот метод возвращает объект PageManager. 3 Вызывается метод PageManager.__getitem__ с аргументом ’page1’. В результате получаем объект Page. Так как частей URL у нас больше не осталось, найденный объект Page является контекстом данного запроса. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 39. Маршрутизация запросов Выбор представления После того, как мы нашли контекст, нам нужно выбрать подходящее представление. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 40. Маршрутизация запросов Выбор представления Представления для объектов предметной области определяются на этапе конфигурации. Императивно: 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
  • 41. Маршрутизация запросов Выбор представления Выбор представления учитывает Method Resolution Order. Если не найдено представления для конкретного типа, будет использовано представление для его супертипа. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 42. Маршрутизация запросов Выбор представления Кроме этого, можно определять разные представления для разных HTTP методов, разных значений HTTP заголовков и на основе других предикатов. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 43. Маршрутизация запросов Шаблоны URL Если маршрутизация запросов с помощью обхода графа не подходит, можно использовать сопоставление URL с шаблонами. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 44. Маршрутизация запросов Шаблоны URL Механизм сопоставления URL с шаблонами работает также, как и в Django, Routes и т.д. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 45. Маршрутизация запросов Шаблоны URL Шаблоны URL приложения определяются на этапе конфигурации. Императивно: config . add_route ( view = show_page , path ="/ pages /: page_id " ) или с помощью ZCML: < route view =" views . show_page " path ="/ p /: page_id " /> Андрей Попп: Разработка web-приложений с repoze.bfg
  • 46. Маршрутизация запросов Шаблоны URL Контекст указывается явно: config . add_route ( view = show_page , path ="/ pages /: page_id " , factory=" some_factory " ) или с помощью ZCML: < route view =" views . show_page " path ="/ p /: page_id " factory=" some_factory " /> Андрей Попп: Разработка web-приложений с repoze.bfg
  • 47. Маршрутизация запросов Шаблоны URL Для каждого шаблона можно определить несколько представлений для разных типов контекста: < route name =" pages " path ="/ p /: page_id " factory =" some_factory " /> < view route_name =" pages " for =" Page " /> < view route_name =" pages " for =" MainPage " /> Андрей Попп: Разработка web-приложений с repoze.bfg
  • 48. Маршрутизация запросов Гибридный метод Можно комбинировать обход графа и шаблоны URL: < route name =" pages " path ="/ pages /: category_id /* traverse " factory =" some_factory " /> В этом случае первая URL сначала будет сопоставляться с /pages/:category_id, а оставшаяся часть будет использоована для обхода графа объектов начиная с объекта, произведённого с some_factory. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 49. Маршрутизация запросов Обработка исключений Что происходит, если во время выполнения представления происходит исключение? Андрей Попп: Разработка web-приложений с repoze.bfg
  • 50. Маршрутизация запросов Обработка исключений В этом случае контекст запроса изменяется на текущее исключение и происходит выбор подходящего представления. Представления для исключений регистрируются обычным образом: < view for =" webob . exc . HTTPNotFound " view =" notfound_view " /> Если во время исполнения любого представления произойдёт исключение webob.exc.HTTPNotFound, то исполнение перейдёт к notfound_view. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 51. Шаблонизация По-умолчанию, repoze.bfg предлагает использовать шаблонизатор Chameleon – это реализация Zope Page Templates и Genshi. Кроме того, на pypi присутствует пакет repoze.bfg.jinja2 – для работы с шаблонизатором Jinja2. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 52. Шаблонизация Как уже упоминалось, представление должно возращать объект с интерфейсом Response. Это не всегда удобно, особенно когда дело касается тестирования, а представление рендерит тяжёлый шаблон: response = myview ( request ) assert ’ Some text ’ in ’ ’. join ( response . app_iter ) Андрей Попп: Разработка web-приложений с repoze.bfg
  • 53. Шаблонизация Repoze.bfg предлагает следующее решение: Представления возвращает dict() объект. За преобразование этого объекта в конечный Response ответственнен отдельный объект – рендерер. Рендерер определяется для каждого представления на этапе конфигурации. Шаблоны являются рендерерами. < view view =" views . some_pages " renderer =" list_pages . jinja2 " /> Андрей Попп: Разработка web-приложений с repoze.bfg
  • 54. Шаблонизация В repoze.bfg по-умолчанию присутствуют рендереры для вывода JSON и ZPT шаблонов. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 55. Шаблонизация Пакет repoze.bfg.jinja2 предоставляет рендерер для шаблонов Jinja2. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 56. Заключение На этом всё. Читайте документацию – http://docs.repoze.org/bfg/. Андрей Попп: Разработка web-приложений с repoze.bfg
  • 57. Спасибо! Вопросы? Андрей Попп: Разработка web-приложений с repoze.bfg