Fork me on GitHub
24/12/2006

Выбор веб-фреймворка: мое решение - Pylons

Напомню тему разговора: выбираем инструмент для веб-интерфейса Twisted-сервиса. Django и Nevow уже рассмотрены, теперь очередь Pylons.

Предыстория

Прежде всего меня привлек блог Groovie автора Pylons Бена Бангерта. Статьи, которые подтолкнули меня к изучению Pylons:

  • Porting Routes from Rails - пояснение, зачем и почему портирован Routes с Ruby на Python.
  • Best of breed Controllers for MVC web frameworks - великолепный обзор способов диспечеризации URL-object (явный, неявный, программный) и реализации контроллеров (исполняемый объект, метод класса, функция). По этой классификации рассматриваются Aquarium, Bricks, CherryPy, Django, Myghty, Rails.
  • Python Web Framework Niches - статья о том, что каждый фреймворк (говорится о Django и TurboGears) имеет свою нишу, и не надо устраивать битву Горцев (должен остаться только один).
  • Project/Code Re-Use, TurboGears and Django - небольшой анализ TurboGears и Django в контексте реиспользования кода
  • Ingredients to the Pylons Python Web Framework - замечательная статья, объясняющая из каких "кирпичиков" построен Pylons. По ходу дела объясняется, почему выбраны именно эти. "Раствором", который скрепляет "кирпичики", служит WSGI.

Как видно, Бен перед тем как писать свой собственный фреймворк, достаточно глубоко изучил уже существующие решения. Мне это понравилось. Он не стал изобретать велосипед, а использовал уже готовые компоненты, причем для связи взял стандартный протокол. Мне это тоже понравилось. Мельком глянул документацию и примеры, прошел туториал. Стиль приложения мне понравился. После этого я добавил Pylons как вариант платформы, на которой буду писать будущий проект.

Тестовое приложение на Pylons

Неожиданностей не было. Всё получилось легко и непринужденно. Сам процесс доставил мне удовольствие. Немного не понравились Mygthy-шаблоны. Думаю, что я буду использовать другие (Pylons позволяет это).

Количество сгенерированного кода

Для создания "рыбы" Pylons-проекта служит команда paster create:

pythy@axcel:~/tmp/py$ paster create --template=pylons pylonsex

Поначалу меня смутило количество сгенерированного кода, я даже думал использовать минималистский вариант -- шаблон pylons_minimal. Меня не пугали небольшие расхождения с документацией (которая ориентирована на шаблон pylons), но почти написав приложение, я понял, что прихожу к стандартному шаблону, так что есть смысл использовать его.

Что же имеем в "рыбе":

PylonsFish
|-- PylonsFish.egg-info                                 # Каталог с метаданными для setuptools
|   |-- PKG-INFO                                        # Информация о пакете
|   |-- SOURCES.txt                                     # Список файлов, которые необходимо включить в пакет
|   |-- dependency_links.txt                            # URL'ы, где искать зависимости пакета
|   |-- entry_points.txt                                # Точки входа, какие плагины реализует пакет
|   |-- paste_deploy_config.ini_tmpl                    # Шаблон для настроек paste.deploy
|   |-- paster_plugins.txt                              # Какие paste-плагины используются
|   |-- requires.txt                                    # Зависимости пакета (Pylons>=0.9.3)
|   `-- top_level.txt                                   # Имя Python-пакета (т.е. pylonsfish)
|-- README.txt                                          # Минимальный readme
|-- development.ini                                     # Paste-настройки для окружения разработчика
|-- pylonsfish                                          # Собственно само приложение
|   |-- __init__.py                                     # Мини-загрузчик WSGI-приложения
|   |-- config                                          # Настройки приложения
|   |   |-- __init__.py                                 # -
|   |   |-- environment.py                              # Основные переменные окружения (где находятся контроллеры, шаблоны, и т.д.)
|   |   |-- middleware.py                               # Используемые WSGI middleware
|   |   `-- routing.py                                  # Управление URL'ами
|   |-- controllers                                     # Контроллеры
|   |   |-- __init__.py                                 # -
|   |   |-- error.py                                    # Контроллер для управления ошибками (404, 500 и т.д.)
|   |   `-- template.py                                 # Контроллер для прямой отрисовки шаблонов
|   |-- docs                                            # Документация к проекту
|   |   `-- index.txt                                   # Краткая информация, как компилировать документацию в html
|   |-- i18n                                            # Каталог для переводов
|   |   `-- __init__.py                                 # -
|   |-- lib                                             # Каталог для проект-специфичных библиотек
|   |   |-- __init__.py                                 # -
|   |   |-- app_globals.py                              # Глобальные объекты
|   |   |-- base.py                                     # Базовый набор для контроллера
|   |   `-- helpers.py                                  # Помощники (всё, что в этом модуле доступно через h-объект)
|   |-- models                                          # Модели
|   |   `-- __init__.py                                 # заглушка для SQLObject
|   |-- public                                          # Статический контент
|   |   `-- index.html                                  # Мини-помощь
|   |-- templates                                       # Каталог для шаблонов
|   |   `-- autohandler                                 # Базовый Mygthy-шаблон
|   |-- tests                                           # Тесты для приложения
|   |   |-- __init__.py                                 # Подготовка тестового окружения
|   |   |-- functional                                  # Функциональные тесты (тесты контроллеров)
|   |   |   `-- __init__.py                             # -
|   |   `-- test_models.py                              # Тесты моделей
|   `-- websetup.py                                     # Дополнительные настройки
|-- setup.cfg                                           # Настройки setuptools
`-- setup.py                                            # setup.py для пакета/egg

Буквально на днях Макс Ищенко задал вопрос о размере "рыбы". Разработчики пояснили свою позицию: они предпочитают выносить часть кода в приложение, обходясь без черной магии в самом фреймворке и предоставляя разработчику модифицировать этот код как ему удобней.

Напомню URL'ы, которые нужно обрабатывать:

  • / - базовый URL
  • /forms - пример рыботы с формами
  • /selfcode - код приложения
  • /dynamic - псевдо-динамическая страница

Я не стал, как в Django, назначать каждому URL'у отдельный контроллер, а просто в рамках одного контроллера назначил URL'ы различным действиям (action):

map.connect(':action', controller='simple')

И создал контроллер simple:

pythy@axcel:~/tmp/py/pylonsex/pylonsex$ paster controller simple

Потом в controllers/simple.py добавил необходимые мне действия. По стилю Pylons-контроллеры весьма похожи на Django-виды, так что я достаточно быстро всё сделал. В отличии от Nevow, мне без особых сложностей удалось воспроизвести один-к-одному поведение тестового Django-приложения (это касается отображения формы и ее ошибок). Я не сказал бы, что в восторге от Myghty-шаблонов, но никаких особых неудобств они не доставляют.

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

Итог

Pylons мне понравился. При работе с ним я получаю удовольствие. В итоге, для себя я решил: если в проект вписывается Django-админка, то я использую Django; если она не нужна - я использую Pylons. Так что открыта новая категория: Pylons и продолжение обязательно будет...

Код приложения, как всегда, на google.code.com.

Комментарии

Все статьи