ComponentLookupError при запросе реестра во время запуска - PullRequest
6 голосов
/ 14 июня 2011

Я создаю приложение, которое запрашивает некоторые данные во внешней реляционной базе данных, используя colle.lead (trunk). Пользователь может изменить настройки подключения к базе данных с помощью специального инструмента панели управления Plone (я следовал примеру в книге Aspeli's Professional Plone Development). Настройки базы данных запрашиваются следующим образом.

База моего продукта configure.zcml устанавливает утилиту для базы данных:

<include package="plone.app.registry" />
<include package="collective.lead" />

<i18n:registerTranslations directory="locales" />

<utility
  provides="collective.lead.interfaces.IDatabase"
  factory=".dbsettings.CalculatorDatabase"
  name="test.calc.db"
  />

dbsettings.py имеет:

from zope.component import getUtility
from plone.registry.interfaces import IRegistry

class CalculatorDatabase(Database):

    @property
    def _url(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(IDatabaseSettings)
        return URL(
            drivername=settings.drivername,
            username=settings.username,
            password=settings.password,
            host=settings.hostname,
            port=settings.port,
            database=settings.database,
        )

Это вызывает исключение ComponentLookupError во время выполнения:

File "/home/zope/envs/test-web/src/test.calc/test/calc/dbsettings.py", line 38, in _url
    registry = getUtility(IRegistry)
File "/home/zope/envs/test-web/eggs/zope.component-3.7.1-py2.6.egg/zope/component/_api.py", line 171, in getUtility
    raise ComponentLookupError(interface, name)
zope.configuration.config.ConfigurationExecutionError: <class 'zope.component.interfaces.ComponentLookupError'>: (<InterfaceClass plone.registry.interfaces.IRegistry>, '')
in:
File "/home/zope/envs/test-web/src/test.calc/test/calc/configure.zcml", line 26.2-30.6
<utility
  provides="collective.lead.interfaces.IDatabase"
  factory=".dbsettings.CalculatorDatabase"
  name="test.calc.db"
  />

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

Спасибо.

Ответы [ 3 ]

6 голосов
/ 14 июня 2011

colle.lead был заменен http://pypi.python.org/pypi/z3c.saconfig, который позволяет вам определять соединения с базой данных в zcmlЕго можно использовать с http://pypi.python.org/pypi/collective.saconnect, если вам требуется панель управления для настройки соединения.

5 голосов
/ 14 июня 2011

То, что Стив упоминает, является корнем проблемы, поэтому я добавлю обходной путь только для случаев, когда вы не можете выполнять обработку исключений.В аналогичном сценарии мне нужно было зарегистрировать утилиту, которая зависела от настроек, хранящихся в реестре.Утилита не может быть зарегистрирована без этих настроек, поэтому я абсолютно хотел, чтобы все происходило по порядку.

Обходной путь должен был не зарегистрировать утилиту в zcml, но вместо этого сделать это внутриподписчик:

<subscriber
    for="Products.CMFPlone.interfaces.IPloneSiteRoot
         zope.app.publication.interfaces.IBeforeTraverseEvent"
    handler=".component.setupStuff"
    />

Это гарантирует, что setupStuff будет иметь доступ ко всем локальным утилитам.Также обратите внимание, что setupStuff также будет быстро возвращаться после запроса, если утилита уже существует, так как подписчик будет срабатывать при каждом запросе.

5 голосов
/ 14 июня 2011

Реестр является локальным компонентом.Каждый сайт Plone (а их может быть много в базе данных) имеет свой собственный.Таким образом, это зависит от контекста.

Zope вычисляет этот контекст в процессе обхода (связывание URL с объектом).Это (в значительной степени) означает, что вы можете искать реестр только в контексте запроса.Таким образом, вы не можете искать реестр в загрузочном коде.

Это может привести к проблемам при написании кода.Одним из решений является встраивание поиска в try /, за исключением того, что он корректно обрабатывает исключение поиска, если у вас еще нет контекста обхода.

...