Программист
0,0
рейтинг
11 ноября 2010 в 13:09

Разработка → Pylons и repoze.bfg объединяются в проект Pyramid из песочницы

Информация всплыла благодаря бурно развернувшейся дискуссии в в официальной группе проекта. Конкретно стало известно, что:
  • веб-фреймворк Pylons, не так давно добравшийся до релиза 1.0, в нынешнем виде прекращает своё развитие. Несмотря на то, что полная поддержка ветки 1.x будет осуществляться на протяжении ещё нескольких лет, никаких архитектурных изменений и новшеств в проект вноситься не будет;
  • имя «Pylons» теперь следует связывать с зонтичным брендом «проект «Pylons», который будет охватывать разработку всех технологий, пожелавших примкнуть к сообществу (по похожему пути идёт развитие проектов под зонтом «Pocoo», среди которых можно отдельно отметить WSGI-стек Werkzeug, шаблонный движок Jinja 2 и систему документирования python-проектов Sphinx);
  • главной технологией в рамках проекта Pylons на сегодняшний день является веб-фреймворк Pyramid, распространяемый по лицензии, производной от BSD.


Данным сообщением мне хотелось бы уведомить всех разработчиков, использующих или планировавших использовать Pylons в своих проектах о сложившейся ситуации вокруг этого веб-фреймворка. Официального объявления от мейнтейнеров ещё не поступило, но его стоит ожидать в ближайшем будущем.
Убедительно рекомендуется пересмотреть свои планы по использованию Pylons-1.x.
С точки зрения новых проектов, очевидно стоит уже сейчас приобщаться к Pyramid, или выбирать любую другую альтернативную технологию — тот же Werkzeug, Django и прочие, непроизводные от Pylons фреймворки.
Для тех же, кто в данный момент уже ведёт разработку на Pylons, вариантов дальнейших действий не так много:
  • оставаться на ветке 1.x и спокойно вести свои проекты до тех пор, пока этого позволяет функциональность фреймворка.
    Всё же в текущем состоянии Pylons очень стабилен, минималистичен (состоит всего из чуть более 2000 (двух тысяч) строк кода), а все взаимозаменяемые сторонние модули продолжают активно развиваться. В случае необходимости, доработать фреймворк до своих возросших потребностей не составит большого труда;
  • попытаться перенести свой проект на новые рельсы (ну… да, если смелость и мотивация позволяют, то можно и сразу на RoR), пока он ещё не разросся в масштабах и не «прилип» намертво к замороженной платформе.

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

О сущности пирамид

Pyramid вырос из веб-фреймворка BFG (известного также под именем repoze.bfg), который в свою очередь является потомком платформы Zope, но разрабатывался под сильным впечатлением от Django и Pylons. В этом году разработчики BFG и Pylons решили объединить свои усилия и имеющиеся наработки в рамках обоих проектов, в результати чего появился новый фреймворк (занятно, но в имеющейся документации используется прошедшее время — «Until the end of 2010, Pyramid was known as repoze.bfg; it was merged into the Pylons project at the end of 2010»). В качестве ключевых характеристик проекта, которым уделялось максимум внимания, разработчики отмечают:
  • низкий порог вхождения;
  • минимализм;
  • скорость (производительность);
  • максимально полная и актуальная документация (разработчики отмечают, что благодаря небольшой кодовой базе им отлично удаётся поддерживать документацию в полном и актуальном состоянии);
  • надёжность (каждый релиз имеет 100% покрытие кода юнит-тестами);
  • открытость.

По архитектуре, Pyramid находится где-то посередине между Django/Pylons/любого другого WSGI-тулкита и Zope-платформой, в результате чего у разработчика появляется свобода выбора в подходах к настройке некоторых компонентов системы:
  • поддерживается декларативный стиль настройки веб-приложений через конфигурационные файлы Zope (ZCML, формат на базе XML)...
  • … в то же время, фреймворк позволяет использовать чисто императивный подход Pylons с его INI-конфигами (создание объектов вручную, их настройка в соответствии с параметрами INI-конфига и последующий вызов методов этих объектов в нужных местах);
  • поддерживается traversal-алгоритм для поиска и вызова обработчика запросов (спуск «от корневого объекта — к — вложенным» по графу model-объектов в строгом соответствии с иерархией, отраженной в запрошенном URL). Подобный подход также применяется в фреймворке CherryPy...
  • … в то же время, разрешается использовать стандартный метод маршрутизации URL по шаблону (URL Dispatch), как это сделано в Pylons и Django, а также допустим смешанный подход из traversal-алгоритма и маршрутизации по шаблону;
  • Pyramid использует архитектурный шаблон MVC, однако в несколько видоизменённом виде. Так, компоненты «View» и «Controller» объединены в одну сущность «View», которая отвечает за представление хранимых в «Model» данных, но имеет два различных контекста — «View Callable» и «View Handler».
  • View Callable — это callable-объект (функция, или класс с определённым методом __call__), который отвечает за обработку поступившего запроса. Его ближайшим аналогом в Pylons-приложении является action-метод внутри класса-контроллера. Соответственно сам класс-контроллер является ближайшим аналогом того, что в Pyramid зовётся View Handler;
  • как и Pylons, фреймворк не навязывает разработчику никаких конкретных технологий для хранения и управления данными.

Собственная кодовая база Pyramid состоит примерно из 5000 (пяти тысяч) строк кода, против чуть больше 2000 строк в Pylons-1.0. Вся остальная функциональность реализуется за счёт сторонних пакетов, входящих в список зависимостей проекта.

Ниже представлен список пакетов, которые поставляются вместе с Pylons-1.0 и Pyramid-1.0a1. Вывод получен с помощью утилит virtualenv и pip.

Станадртная комплектация Pylons

Beaker==1.5.4
FormEncode==1.2.3dev
Mako==0.3.5
MarkupSafe==0.11
Paste==1.7.5.1
PasteDeploy==1.3.4
PasteScript==1.7.3
Pygments==1.3.1
Pylons==1.0
Routes==1.12.3
Tempita==0.5dev
WebError==0.10.2
WebHelpers==1.2
WebOb==1.0
WebTest==1.2.3
decorator==3.2.0
nose==0.11.4
simplejson==2.1.2
wsgiref==0.1.2

Станадртная комплектация Pyramid

Beaker==1.5.4
Chameleon==1.2.13
Mako==0.3.5
MarkupSafe==0.11
Paste==1.7.5.1
PasteDeploy==1.3.4
PasteScript==1.7.3
WebOb==1.0
pyramid==1.0a1
repoze.lru==0.3
translationstring==0.3
venusian==0.4
wsgiref==0.1.2
zope.component==3.10.0
zope.configuration==3.7.2
zope.deprecation==3.4.0
zope.event==3.5.0-1
zope.i18nmessageid==3.5.3
zope.interface==3.6.1
zope.schema==3.7.0
— Pylons: 19.
Pyramid: 20.

В количественном отношении ситуация практически не изменилась — Pyramid так же как и Pylons активно опирается на сторонние технологии и WSGI-стек, — однако налицо структурные изменения. Насколько сильно они повлияют на сложность портирования готового Pylons-приложения — сказать трудно. Пока разработчики только лишь упоминают о причинах, побудивших их пойти на столь радикальные изменения (тут более подробно) и обещают со временем предоставить пользователям Pylons 1.x план по миграции на Pyramid без потери функциональности в уже созданных приложениях.

UPD: В сети появился неофициальный гид по миграции с Pylons-1.0. Но целостность и работоспособность данного решения автором топика ещё не проверялась.

UPD: Сферические тесты в вакууме.
Maxim Avanov @Ghostwriter
карма
2,0
рейтинг 0,0
Программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (54)

  • +2
    Использовал Pylons в нескольких проектах. Очень неплох был. Ну «Live Fast Die Young». Буду возвращаться на django. А для маленьких проектов даже не знаю. Pyramid еще вроде молод. А Werkzeug юзабелен на продакшене?
    • 0
      Ну и что мешает использовать в маленьких проектах всё тот же Pylons 1.x?
      • +1
        Всё ту же джангу. obvious fix
      • 0
        Pylons в принципе можно и нужно использовать, я думаю с текущим положением дел многие не согласятся и сам Пайлонс будет жить долго и счастливо.
    • 0
      Относительно зрелости Pyramid. Фреймворк в большей степени состоит из repoze.bfg, который уже несколько лет имеет стабильную версию. Поэтому
      — если начинать разрабатывать на Pyramid с нуля, то проблем никаких не будет — код полностью стабилен и протестирован;
      — приложения, написанные на BFG, уже сейчас можно легко портировать на новый фреймворк (есть лишь небольшая вероятность в несовместимости со сторонними пакетами, написанными специально под repoze.bfg);
      — с Pylons-проектами сложнее всего — разработчики советуют пока повременить с их портированием, так как часть зависимых пакетов нуждается в переработке (например, библиотека webhelpers имеет несовместимый модуль webhelpers.pylonslib, который активно применяется в проектах на Pylons).
    • +4
      Werkzeug более чем юзабелен
    • 0
      Молоток напрямую не использовал, но использовал Flask. сначало понравилось, а потом стали пугать неявные передачи g (глобальное имя) и всякая магия — поглядите как они SQLAlchemy завернули. Ну зачем было тащить алхимика через себя отображая его. Почему они просто не реализовали начальные настройки в виде простой функции?
      • 0
        Во Flask изначально было огромное кол-во магии. Постепенно ее вытравливают, вроде. Сам Werkzeug нормален.
  • 0
    Я не согласен с автором этой статьи и с разработчиками Pylons которые на это решились.
    У меня очень много претензий к BFG и уже к текущему Pyramid, для меня это не юзабильно.
    • 0
      По необходимости будем писать Pylons3 :)
      • 0
        Моя первая реакция была примерно такой же — форкнуть текущую версию Pylons и начать собственный открытый проект. Сейчас я больше склоняюсь к портированию своего нынешнего Pylons-приложения (около 20,000 строк кода, всё ещё на стадии разработки) на Pyramid, когда разработчики выпустят хотя бы примерный план по миграции.
        Не могли бы вы поподробнее рассказать о своих претензиях именно к Pyramid (c BFG я, к сожалению, знаком только по быстрому туториалу)?
        • 0
          Развёрнуто сейчас не могу писать но если кратко:
          отсутствие или упрощёное понимание ООП, MV с фактически магией для C.
          В Pylons я удобно применял наследование и очень был доволен __before__ и т.д.
          • 0
            В Pyramid, связка ViewHandler(object) -> view_callable() выполняют практически то же самое, что и связка Controller(BaseController) -> action() в Pylons. Существенное различие (и одна из главных концепций новой архитектуры) здесь в том, что вам не нужно иметь специальный базовый класс-контроллер. Это может быть абсолютно любой класс, реализующий исключительно то, что нужно вам! Вам не нужно переопределять функциональность базового класса через его наследование, вы просто пишете такой обработчик, который нужен вам именно в этой части вашего приложения. Это открывает широкие возможности для интеграции готовых сторонних приложений в вашу инфраструктуру на Pyramid.
            Те вещи, которые вы выполняли в Pylons посредством служебных методов типа __before__ и __after__ теперь можно выполнить при помощи механизма событий. Ближайшими аналогами методов __before__ и __after__ могут стать обработчики событий pyramid.events.NewRequest, pyramid.events.ContextFound и pyramid.events.NewResponse, а также любой произвольный код, зарегистрированный через функцию pyramid.request.Request.add_finished_callback(). Вся последовательность обработки запросов, а также точки возникновения указанных событий описаны в этом документе — Request Processing.
            • 0
              Так а можно встроить tmpl_context? «c.» крайне удобно использовать. Всякие return {} это слишком подобно Django.
              Пока мне не нра… и к тому же от структуры ViewHandler не зависит роутинг как я понимаю.
              • 0
                Да, конечно.
                tmpl_context, а также registry (ближайший аналог pylons.config) и многие другие локальные для текущего запроса объекты являются атрибутами объекта request (request.tmpl_context), который передается во View Callable в качестве первого аргумента. А при использовании стандартного URLDispatch-роутинга это будет единственный(!) параметр, который передаётся во View Callable. В Pyramid ушли от практики применения глобальных thread-local StackedObjectProxy-объектов.
                • 0
                  значит надо будет делать каждый раз return {«c»:request.tmpl_context}? или как? Я это так же спрашиваю по тому как на данный момент я в принципе не вижу возможности портироваться с Pylons на это чудо (c bfg это очевидно как).
                  • 0
                    При использовании декоратора для указания шаблона, всё что вам нужно сделать — это вернуть из обработчика запроса словарь, который будет передан в шаблон.
                    @action(renderer='client_index.jinja2')
                    def index(self):
                        return {'views':5, 'clicks':1}
                    

                    Пример из неофициального гида по миграции с Pylons.
                    • +1
                      очень неудобно, если надо рендерить разные шаблоны (по некоторым условиям)
                      • 0
                        у меня название шаблона вообще генерируется в спец. функции в зависимости от глобальных настроек и ситуации.
                    • 0
                      ну я верно наверху написал? Я не хочу словарь я хочу полный проброс tmpl_context в шаблон.
                      • 0
                        Нет. Если вы создали Pyramid-проект по шаблону pylons_basic или pylons_sqla, то request.tmpl_context (c.) авттоматически добавляетсяк списку переменных доступных внутри renderer. Вы просто можете ему передавать параметры и беp tmpl_context, через словарь.

                        За пополнение renderer отвечает следующий модуль внутри вашего проекта (projectname.subscribers):
                        from pyramid.threadlocal import get_current_request
                        from pyramid.exceptions import ConfigurationError
                        from pyramid.url import route_url
                        
                        def add_renderer_globals(event):
                            """ A subscriber to the ``pyramid.events.BeforeRender`` events.  Updates
                            the :term:`renderer globals` with values that are familiar to Pylons
                            users."""
                            request = event.get('request')
                            if request is None:
                                request = get_current_request()
                            globs = {
                                'url': route_url,
                                'h':None,
                                }
                            if request is not None:
                                tmpl_context = request.tmpl_context
                                globs['c'] = tmpl_context
                                globs['tmpl_context'] = tmpl_context
                                try:
                                    globs['session'] = request.session
                                except ConfigurationError:
                                    pass
                            event.update(globs)
                        


                        А tmpl_context доступен нутри view callable через объект request (projectname.handlers):
                        from pyramid.view import action
                        from testproj.models import MyModel
                        
                        class MyHandler(object):
                            def __init__(self, request):
                                self.request = request
                        
                            @action(renderer='mytemplate.mako')
                            def index(self):
                                root = MyModel.by_name('root')
                                c = self.request.tmpl_context
                                c.abc = u'Hello World!'
                                return {'root':root, 'project':'testproj'}
                        
                        • 0
                          тогда разумно использовать для MyHandler
                          def __before__(self): self.c = self.request.tmpl_context
                          • 0
                            да, всё верно. Тогда этот __before__ надо будет подписать к событию pyramid.events.ContextFound
                        • 0
                          В целом понятно, большое спасибо… но всё больше начинает пугать, что Pyramid это некий хамелеон без строгой «политики партии», если вы понимаете о чём я.
                        • 0
                          Да, зря я сразу не посмотрел в эти шаблоны, а то возник вопрос, как в шаблонах урлы формировать без url(). Тем не менее, остаётся вопрос, как это делать «правильно», без передачи 'url': route_url
            • 0
              docs.pylonshq.com/pyramid/dev/narr/models.html — Зопой так и дышит всё…
            • 0
              И всё же я не понимаю причины… ведь всегда можно сделать Controller(BaseController, MyBaseController)
              • 0
                Можно. И это будет отлично работать в рамках отдельно взятого проекта! Но не фреймворка в целом. Любое более-менее серьезное изменение в базовом классе со стороны разработчиков Pylons приведёт к потере совместимости со всеми приложениями, которые используют модифицированную версию базового кнтроллера. Это происходит из-за того, что все методы базового контроллера являются API, хотя не должны выполнять эту роль!. View Handlers в Pyramid отделены от API и избавлены от этого недостатка.
                • 0
                  Угу они просто бояться ломать API и из-за этого такие капитальные изменения… мне кажется это не обоснованно.
                  Хотя они лукавят — если они что то поменяют к примеру в request то тоже посути изменят API и всё поломают.
                  Я понимаю для чего они сделали этот «взгляд со стороны» но мне кажется это всё же не верный путь.
                  Я не вижу большой разницы между методами базового класса и методами какого другого обьекта — они боятся перекрытия? Пусть используют префиксы, в C++ уже давно это практикуют.
                  Для меня это всё ещё мутно.
                  • 0
                    И кто говорит, что Pylons2 должен был быть совместим с Pylons1? Они же решили вообще взять BFG…
            • 0
              Самое важное: docs.pylonshq.com/pyramid/dev/tutorials/wiki2/index.html с алхимией всё оч плохо… а она всё же самая нормальная ORM.
          • 0
            > отсутствие или упрощёное понимание ООП

            Очень не соглашусь, это как раз Pylons грешил чрезмерным использованием наследования — это совсем не путь ООП. Качественная ОО архитектура может опираться на композицию, но не на наследование. Pyramid решает всё это с помощью DI с zope.component.

            > MV с фактически магией для C

            Тут, конечно, могут быть разногласия по поводу терминологии, но я так понимаю вы недовольны object graph traversal? Это совсем не магия, а довольно естественная вещь, почитайте внимательнее документацию и попробуйте использовать у себя в приложении. Для проблемной области, где встречаются связи «контейнер — содержимое» самое то.

            • 0
              Вы о каком то другом ООП говорите так как наследование это основополагающее свойство ООП. Именно наследование мне нравилось в Pylons.

              >но я так понимаю вы недовольны object graph traversal?

              Нет… на счёт этой вещи я пока ещё не сформировал впечатление. Мне не понравилось то, что пропала сама сущность «контроллер» в понимании Pylons.
              • 0
                Просто погуглите на «inheritance vs. composition» :-) да еще и банда 4-х затрагивала эту тему, а вы говорите не тот ООП.
        • 0
          > Сейчас я больше склоняюсь к портированию своего нынешнего Pylons-приложения (около 20,000 строк кода, всё ещё на стадии разработки) на Pyramid

          Простите за тупой вопрос: «А зачем»?

          Раз уж вы накодили столько на Pylons, то, видимо, он покрывает все нужды? А то, что в будущем может понадобиться — очень легко добавить, он очень грамотно написан. По большому счету, ведь, весь Pylons — прослойка между сторонними компонентами.
          • 0
            Есть несколько связанных друг с другом мотивирующих факторов:
            — большая часть кода содержится в библиотеке высокоуровневых компонентов, которые можно использовать в других Pylons-проектах. Есть вероятность открытия этих исходников сообществу;
            — из-за того, что Pylons выполняет роль прослойки между сторонними компонентами, заменить его на прослойку с более гибким интерфейсом и большей функциональностью относительно просто;
            — есть субъективное ожидание, что вокруг нового фреймворка сформируется более крупное сообщество, вливающее в него свои наработки. По крайней мере, предпосылки к этому видны и в архитектуре фреймворка, и в настроениях разработчиков в списках рассылки.
    • 0
      А назовите претензии пожалуйста? Просто интересно, потому, что я сейчас на BFG хочу проект сделать.
  • 0
    Pyramid allows you to «mount» an existing Pylons app and serve it
    right through without modification. Having done so, you are then free
    to convert the app page by page, or handler by handler or however you
    wish to proceed… or leave it unchanged.

    Где-то есть дока?
    • 0
      Насколько я понял, здесь подразумевается возможность использования композитных WSGI-приложений, настраиваемых через конфигурационный файл Pyramid.
      Документации по возможному «прямому» монтированию Pylons-приложения в окружение Pyramid я, к сожалению, пока не встречал.
  • 0
    Уже почитал об этом «событии». Всё-таки до слияния ещё далеко и пайлонс можно использовать для новых проектов. Пирамида ещё успеет измениться, опасно начинать писать на ней живой код.
    Удивило меня сразу несколько вещей:
    1) Один файл views.py.
    2) Один файл models.py.
    Это близко к Django. Могло бы означать, что приложение может иметь структуру дерева просто создавая приложения внутри, которые имплементируют части функционала. Увы, это не так.
    Это указывает на то, что фреймворк стал больше ориентироваться на небольшие приложения, что очень и очень плохо. Да и велик шанс что люди станут всё писать в одном файле, а это просто ужас!
    3) Способ конфигурации(задание рендера etc) контроллеров.
    Сначала мне это дико не понравилось. Быть может лучше было сразу сделать как в TG2, декоратором. Но, как я вижу, в Пирамиде доступен и похожий способ.

    Что я не понял(вообще, не вчитывался, но сразу только не понял сути), так это суть моделей.
    Сказано что это не те модели, что принято было считать. Траверсал сам находит нужную модель по url и делает её(внимание!) контекстом. Это как? Т.е. а Траверсал… жёсткие правила?
    docs.pylonshq.com/pyramid/dev/narr/traversal.html#traversal-algorithm-examples
    Как он находит нужную модель? Контекстом становится экземпляр класса? Какой? Если не экземпляр, то что, просто ссылка на класс?
    Т.е. я всегда должен придерживаться логики site/path/model_name/action? Как оно будет определять контекст если я добавлю хендлер, а не вью?

    В общем, куча вопросов, на которые нет пока ответов.
    Однако, общее впечатление приятное, теперь пайлонс это не просто клей, который приходилось обновлять добавляя недостающие строки или переписывая части проекта, теперь это настоящий веб-фреймворк.
    И ещё, приятно удивило что многие модули repoze переродились как компоненты Пирамиды(например, repoze.who, what, которые я так люблю).
    • 0
      > Это указывает на то, что фреймворк стал больше ориентироваться на небольшие приложения, что очень и очень плохо.

      В дискусии чётко прослеживается желание сделать Pyramid «платформой для остальных фреймворков, функционирующих на более высоком уровне». Вот одна из цитат в переписке:
      «There has also been a dialog with the Django developers the past two
      years, mostly covering basic WSGI issues and a potential common
      request/response object (WebOb). The door is always open if they'd
      like greater collaboration, or to port Django to Pyramid the way TG
      was ported to Pylons. It hasn't gone very far because Django famously
      prefers homegrown code, but we aim to keep the code „Django-ready“ by
      anticipating what hooks they'd likely need for their features.»
      groups.google.com/group/pylons-discuss/msg/43c4dfeea5d5d1bc
      • 0
        Понятно, значит всё это — просто демонстрация.

        В любом случае, остаётся вопрос на счёт определения контекста через Траверсал. Не понятно зачем определение контекста завязано на url_path. Ведь никто это не будет использовать, а если и будет, то поплатится если кто-то вызовет, скажем, не user/delete, а catalog/delete. Ведь тогда вызываться будет один вид, но контексты будут разные.
        • 0
          Собственно, вот то, о чём я говорю:
          docs.pylonshq.com/pyramid/dev/narr/traversal.html#traversal-algorithm-examples
          docs.pylonshq.com/pyramid/dev/designdefense.html#model-traversal-confusion

          И да, судя по docs.pylonshq.com/pyramid/dev/narr/views.html (контекст всегда указывается при добавлении вида), лучше было бы сделать это через :context, а не как сейчас.
          • 0
            вы меня опередили :)
            habrahabr.ru/blogs/python/107946/#comment_3411613
          • 0
            И, Да! Терминология в Пирамидах слишком нетрадиционна для MVC-фреймворка, что придаёт концепциям бОльшую запутанность и сложность, чем есть на самом деле.
        • 0
          Для этого, в алгоритме присутствует параметр «view name». То есть, алгоритм должен определить не только контекст (последний существующий(!) объект в указанной иерархии), но имя view callable. Но это пока лишь только найденный тип объекта (контекст) и имя обработчика (view callable). С их помощью начинается поиск подходящей комбинации (цитата из документации):
          «Using the view name (baz) and the type, view lookup asks the application registry this question: Please find me a view callable registered using a view configuration with the name “baz” that can be used for the class Bar.»

          Поэтому здесь можно однозначно определить, кто есть обработчик для /user/delete, а кто для /catalog/delete. Конкретно данном случае у нас будет два разных контекста — delete_внутри_user (т.к. мы попадаем в delete только в том случае, если находим user, а иначе контекст был бы user) и delete_внутри_catalog. Т.к. у нас не осталось части url для обозначения имени для view callable, будет использоваться view callable по-умолчанию.

          Вообще, мне самому не очень нравится Traversal-алгоритм. В своё время из-за него я бросил изучать CherryPy, т.к. посчитал данный подход способствующим распространению ошибок, допущенных по невнимательности. Но в Pyramid есть хороший пример, демонстрирующий, что в URL'ах с произвольной иерархией объектов Traversal-алгоритм оказывается предпочтительнее простого URLDispatch.
          • 0
            Значит будет вид, добавленный с именем delete и контекстом по-умолчанию models.User.
            При /user/delete, будет дёрнут именно этот вид, при /catalog/delete — корневой.
            Если вид с именем delete, но без контекста, то он вообще не будет вызван? Или будет вызываться всегда?
            >у нас будет два разных контекста
            Ты хотел сказать «вида»?
            Что значит «внутри»? Т.е. виды, которые определены в модели? Их там можно определять?
            Или будет вызвана функция модели, а зачем только вид?
            Судя по всей логике, он просит найти вид, имеющий имя и содержащий в описании указание на использование этого контекста.
            • 0
              Ok, вот как оно работает.
              Всегда, когда мы имеем дело с Traversal-алгоритмом, во время инициализации приложения мы должны указать маршрутизатору приложения фабрику, которая будет порождать для для каждого поступившего запроса корневой объект графа:
              config = Configurator(root_factory=Root)
              

              Корневой объект — это наша точка отсчёта. Стартовая позиция, от которой мы будем искать контекст. Если бы мы не использовали Traversal-алгоритм, а использовали URLDispatch, то контекст для нас всегда бы был этим корневым объектом. Всегда!
              Сама фабрика, порождающая корневой объект, в простейшем случае выглядит примерно так:
              class Root(dict):
                  def __init__(self, request):
                      pass
              

              Вообще говоря, вместо pass здесь должен быть return какого-либо объекта. Самое главное, чтобы он имел системный метод __getitem__. Этот объект и будет нашим корневым объектом.
              Здесь есть ещё один нюанс — если мы укажем во время инициализации приложения нашу root-фабрику, то Pyramid будет использовать свою, дефолтную фабрику, которая возвращает объект без каких-либо вложенных объектов внутри себя. КАК РАЗ ЭТИ ВЛОЖЕННЫЕ ОБЪЕКТЫ (и которых нет у дефолтного) и называются «models». Это не те model, которые в MVCфреймворках под буквой M. Это Graph Models.

              И вот к нам поступили запросы. Мы имеем два разных URL:
              1) example.com/user/delete
              2) example.com/catalog/delete
              Traversal начинает с того, что создает root object для каждого запроса и получает иерархию из PATH_INFO:
              1) hierarchy = ['user', 'delete']
              2) hierarchy = ['catalog', 'delete']
              Затем, он делает
              segment = hierarchy.pop(0)
              root.__getitem__(segment)
              

              Если не славливаем exception, то временным контекстом становится объект, полученный от __getitem__. Повторяем это действие до тех пор, пока не словим исключение. Если славливаем — то контекст уже определён (иерархия закончилась), и дальше мы имеем дело только с view name. Если мы прошли все сегменты, то контекстом считается последний сегмент, а в качестве view name будет пустая строка (по дефолту).
              Поэтому я и говорю, что контексты delete для двух разных запросов лежат «внутри» разных иерархий, начатых с root object. Фактически, наш root object на верхнем уровне должен содержать два члена — грубо говоря, root — это контейнер, который содержит в себе user и catalog. Сами user и catalog — тоже контейнеры, которые содержат в себе delete (но каждый — свой собственный delete).

              После того, как мы нашли context и view name (Traversal завершил работу, теперь нам надо найти подходящий view callable, удовлетворяющий условиям текущих context и view name), мы начинаем искать:
              1) «Using the view name ('' — empty string, default) and the type (user), view lookup asks the application registry this question: Please find me a view callable registered using a view configuration with the name “some_default_name” that can be used for the class User.»
              2) «Using the view name ('' — empty string, default) and the type (catalog), view lookup asks the application registry this question: Please find me a view callable registered using a view configuration with the name “some_default_name” that can be used for the class Catalog.»

              Вроде ничего не забыл :)
              • 0
                *Здесь есть ещё один нюанс — если мы _НЕ_ укажем…
              • 0
                Ещё одное пояснение из документации относительно Graph Models:
                «Graph model — is an object representing data in the system. If traversal is used, a model is a node in the object graph traversed by the system. When traversal is used, a model instance becomes the context of a view.»
                docs.pylonshq.com/pyramid/dev/glossary.html#term-model
              • 0
                Прошу у всех прощения за разведённый флуд. Похоже я устал. Ещё один фикс для полного понимания. Поиск ведется по таким критериям:

                1) «Using the view name ('' — empty string, default) and the type «delete» (in root.user), view lookup asks the application registry this question: Please find me a view callable registered using a view configuration with the name “some_default_name” that can be used for the class Delete
                2) «Using the view name ('' — empty string, default) and the type «delete» (in root.catalog), view lookup asks the application registry this question: Please find me a view callable registered using a view configuration with the name “some_default_name” that can be used for the class Delete

                У нас два разных класса Delete, вложенных в два разных контейнера.
    • 0
      В целом с вами согласен — оочень похоже, что это для чего то мелкого и быстрого тогда как Pylons всё же более масштабная вещь и удобная в крупных проектах. Мне кажется Pylons в текущем виде всёравно будет развиваться, просто у Pyramid свой путь… иной, а нам плиз дальше Pylons нужен. :)
      • 0
        Не совсем понимаю, с чего вы взяли, что pyramid для чего-то мелкого?

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