在启动时查询注册表时发生ComponentLookupError

|| 我正在构建一个应用程序,该应用程序使用Collective.lead(树干)查询外部关系数据库中的某些数据。用户可以在自定义的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\"
  />
为什么在运行时找不到注册表?我究竟做错了什么? 谢谢。     
已邀请:
        史蒂夫提到的是问题的根源,因此,我将仅针对无法执行异常处理的情况添加解决方法。在类似的情况下,我需要注册一个实用程序,该实用程序取决于存储在注册表中的设置。没有这些设置便无法注册该实用程序,因此我绝对希望事情能够按顺序进行。 解决方法是不在zcml中注册实用程序,而是在以下订户中进行注册:
<subscriber
    for=\"Products.CMFPlone.interfaces.IPloneSiteRoot
         zope.app.publication.interfaces.IBeforeTraverseEvent\"
    handler=\".component.setupStuff\"
    />
这样可以保证“ 4”可以访问所有本地公用程序。还要注意,“ 4”在查询该实用程序是否已存在之后也会迅速返回,因为订户将在每个请求上触发。     
        Collective.lead已被http://pypi.python.org/pypi/z3c.saconfig取代,它允许您在zcml中定义数据库连接。如果需要控制面板来配置连接,可以将其与http://pypi.python.org/pypi/collective.saconnect一起使用。     
        注册表是本地组件。每个Plone站点(数据库中可能有很多站点)都有自己的站点。因此,它取决于上下文。 Zope在遍历(URL与对象的连接)过程中找出该上下文。这(几乎)意味着您只能在请求的上下文中查找注册表。因此,您无法在启动代码中查找注册表。 这可能导致编写代码的麻烦。一种解决方案是将查找嵌入try / except中,如果您还没有遍历上下文,那么它将优雅地处理查找异常。     

要回复问题请先登录注册