2011-06-14 38 views
6

我正在構建一個應用程序,該應用程序使用collective.lead(trunk)查詢外部關係數據庫中的某些數據。用戶可以在自定義的Plone控制面板工具中修改數據庫連接設置(我遵循Aspeli的專業Plone開發手冊中的示例)。以這種方式查詢數據庫設置。在啓動時查詢註冊表時ComponentLookupError

我的產品的基本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" 
    /> 

爲什麼不在運行時找到註冊表?我究竟做錯了什麼?

謝謝。

回答

5

Steve提到的是問題的根源,所以我只會針對無法進行異常處理的情況添加解決方法。在類似的情況下,我需要註冊一個依賴於存儲在註冊表中的設置的實用程序。如果沒有這些設置,該實用程序無法註冊,所以我絕對希望事情順序發生。

的解決方法是登記在ZCML的效用,而是做以下的用戶中:

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

這將保證setupStuff將有機會獲得所有當地的公用事業。另請注意,setupStuff也會在查詢公用程序是否已存在後很快返回,因爲訂戶將在每個請求上觸發。

+0

謝謝。這是最乾淨的解決方案。 – zedr 2011-06-14 16:35:15

5

註冊表是本地組件。每個Plone站點(並且數據庫中可能有很多)都有自己的站點。所以,它依賴於上下文。

Zope在遍歷過程中(連接一個URL到一個對象)找出這個上下文。這(幾乎)意味着您只能在請求的上下文中查找註冊表。所以,你不能在啓動代碼中查找註冊表。

這可能會導致雞和雞蛋問題編寫代碼。一種解決方案是將查找嵌入到try /中,除非如果還沒有遍歷上下文,它將優雅地處理查找異常。

+0

感謝您的洞察力。我確實通過添加一個try來緩解這個問題:except:子句默默地讓錯誤通過,直到對象獲得上下文爲止。 – zedr 2011-06-14 16:36:18

相關問題