2011-06-14 2 views
6

collective.lead (트렁크)를 사용하여 외부 관계형 데이터베이스의 일부 데이터를 쿼리하는 응용 프로그램을 빌드하고 있습니다. 사용자는 사용자 정의 Plone 제어판 도구에서 데이터베이스 연결 설정을 수정할 수 있습니다 (Aspeli의 Professional Plone Development 설명서의 예를 따랐습니다). 데이터베이스 설정은 이런 식으로 쿼리됩니다.시작할 때 레지스트리를 쿼리 할 때 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이있다 : 이것은 런타임에 ComponentLookupError 예외를 제기

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, 
     ) 

:

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

스티브가 언급 한 것은 문제의 근원이므로 예외 처리를 할 수없는 경우에 대한 대안을 추가 할 것입니다. 비슷한 시나리오에서 레지스트리에 저장된 설정에 의존하는 유틸리티를 등록해야했습니다. 이 설정 없이는 유틸리티를 등록 할 수 없으므로 나는 순서대로 일어날 것을 절대적으로 원했습니다. 이 setupStuff 모든 지역의 유틸리티에 액세스 할 것이라는 점을 보장 할 것

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

:

해결 방법은 다음과 가입자 안에 그것을 대신 zcml에서 유틸리티를 등록하지만 하지이었다. 구독자가 모든 요청에 ​​대해 트리거하므로 유틸리티가 이미 존재하는지 쿼리 후 setupStuff도 빨리 반환됩니다.

+0

감사합니다. 가장 깨끗한 솔루션입니다. – zedr

5

레지스트리는 로컬 구성 요소입니다. Plone 사이트마다 (데이터베이스에 많은 사이트가있을 수 있음) 자체 사이트가 있습니다. 그래서 상황에 따라 다릅니다.

Zope는 트래버스 과정에서 해당 컨텍스트를 파악합니다 (URL 연결). 그 (꽤)는 요청의 컨텍스트에서 레지스트리를 찾을 수 있다는 것을 의미합니다. 따라서 시작 코드에서 레지스트리를 찾을 수 없습니다.

이렇게하면 코드를 작성하는 데 닭고기 및 계란에 문제가 발생할 수 있습니다. 한 가지 해결책은 탐색 컨텍스트가 아직없는 경우 조회 예외를 정상적으로 처리하는 try/except에 조회를 포함하는 것입니다.

+0

통찰력에 감사드립니다. 실제로 try : except : 절을 추가하여 문제를 완화했습니다. 객체가 컨텍스트를 얻을 때까지 오류를 자동으로 전달합니다. – zedr

관련 문제