Появилась у меня задача внести изменение в логику работы стандартного объекта запроса. В предыдущей статье я рассказывал откуда берется запрос и как он попадает в публикатор.
Далее подразумевается работа с HTTP запросом, но, думаю, понимая общие принципы можно добиться нужного результата и с другими типами запросов.
С чего начать?
Для начала нам необходимо создать собственный объект, пусть это будет CustomRequest, и унаследовать его от BrowserRequest, который можно найти в файле /path/to/zope/publisher/browser.py. Далее реализуете собственную расширенную функциональность в соответствии с вашей задачей.
Регистрация компонента
Теперь у нас есть собственный объект запроса, осталось только сказать публикатору Zope чтобы он использовал его вместо запроса по умолчанию. Зарегистрируем новый объект запроса как утилиту в файле конфигурации нашего компонента, например как показано ниже:
<configure
xmlns="http://namespaces.zope.org/zope">
<utility
component=”.publication.CustomRequest”
provides=”zope.app.publication.interfaces.IBrowserRequestFactory”
/>
<class class=”.publication.CustomRequest”>
<require like_class=”zope.publisher.browser.BrowserRequest” />
</class>
<class class=”.publication.CustomRequest”>
<require like_class=”zope.publisher.browser.BrowserResponse” />
</class>
</configure>
Как это работает?
При публикации сервер обращается к фабрике HTTPPublicationRequestFactory (см. /path/to/zope/app/publication/httpfactory.py) где в методе __call__ по заданным параметрам производится поиск в реестре фабрик (публикаторов) с интерфейсом IRequestPublicationFactory. Стандартный их список можно найти в файле /path/to/zope/app/publication/configure.zcml. Найденная фабрика возвращает класс запроса и публикатора. В нашем случае этой фабрикой будет BrowserFactory (см. /path/to/zope/app/publication/requestpublicationfactories.py):
-
-
class BrowserFactory(object):
-
-
implements(IRequestPublicationFactory)
-
-
def canHandle(self, environment):
-
return True
-
-
def __call__(self):
-
request_class = component.queryUtility(
-
interfaces.IBrowserRequestFactory, default=BrowserRequest)
-
return request_class, BrowserPublication
Как видно из кода, фабрика ищет утилиту, зарегистрированную под интерфейсом IBrowserRequestFactory. Так что найдет она наш класс запроса, который мы зарегистрировали выше.
Если же не зарегистрированно ни одной утилиты с этим интерфейсом, будет использован стандартный класс BrowserRequest.
30 Август 2008
Грасиас за статью. Как раз на днях заинтересовался исследованием этой темы - и вот - ваш пост! Очень кстати!