从Zope的模式圆形进口引用(circular import references from zop

2019-07-31 09:40发布

我遇到非常类似的问题这太问题 ,但我的申请,这些以前的答案的企图是不会通,并建议我开始它作为一个新的问题:

在下面的代码我定义一对getChoices()函数,我认为会推迟圆形裁判,但没有!? 什么是错在这里吗?

# ns.content/ns/content/foo.py
from zope import schema
from plone.directives import form
from z3c.relationfield.schema import Relation, RelationChoice
from plone.formwidget.contenttree import ObjPathSourceBinder

class IFoo(form.Schema):

    def getBarChoices():
        # avoiding circular refs...
        from bar import IBar
        return ObjPathSourceBinder(object_provides=IBar.__identifier__)

    barChoices = getBarChoices()
    form.widget(bar=AutocompleteFieldWidget)
    bar = Relation(source= barChoices,required=False)

# ns.content/ns/content/bar.py
from zope import schema
from plone.directives import form
from z3c.relationfield.schema import Relation, RelationChoice
from plone.formwidget.contenttree import ObjPathSourceBinder

class IBar(form.Schema):

    def getFooChoices():
        # avoiding circular refs...
        from foo import IFoo
        return ObjPathSourceBinder(object_provides=IFoo.__identifier__)

    fooChoices = getFooChoices()
    form.widget(foo=AutocompleteFieldWidget)
    foo = Relation(source= fooChoices,required=False)

resultingError = """
  File ".../buildout-cache/eggs/martian-0.11.3-py2.7.egg/martian/scan.py", line 217, in resolve
    __import__(used)
  File ".../zeocluster/src/ns.content/ns/content/bar.py", line 32, in <module>
    class IBar(form.Schema):
  File ".../zeocluster/src/ns.content/ns/content/bar.py", line 48, in IBar
    fooChoices = getFooChoices()
  File ".../zeocluster/src/ns.content/ns/content/bar.py", line 38, in getFooChoices
    from ns.content.foo import IFoo
  File ".../zeocluster/src/ns.content/ns/content/foo.py", line 33, in <module>
    class IFoo(form.Schema):
  File ".../zeocluster/src/ns.content/ns/content/foo.py", line 73, in IFoo
    barChoices = getBarChoices()
  File ".../zeocluster/src/ns.content/ns/content/foo.py", line 39, in getBarChoices
    from ns.content.bar import IBar
zope.configuration.xmlconfig.ZopeXMLConfigurationError: File ".../zeocluster/parts/client1/etc/site.zcml", line 16.2-16.23
    ZopeXMLConfigurationError: File ".../buildout-cache/eggs/Products.CMFPlone-4.2.0.1-py2.7.egg/Products/CMFPlone/configure.zcml", line 102.4-106.10
    ZopeXMLConfigurationError: File ".../zeocluster/src/ns.content/ns/content/configure.zcml", line 18.2-18.27
    ImportError: cannot import name IBar
"""

Answer 1:

你打电话getBarChoices()在定义时,定义的类时IFoo 。 所以, from bar import IBar将在分析被执行foo.py导致圆形进口。

据我看到它,你有两种基本的选择:

1)使用一个字符串作为标识符object_provides。

你这样做,反正已经使用IFoo.__identifier__ ,但如果你把它的静态而非动态,这将消除你的循环依赖:

source = ObjPathSourceBinder(object_provides='ns.content.bar.IBar')
bar = Relation(source=source,required=False)

不需要输入IBarfoo.py 。 这具有明显的缺点是位置IBar现在是硬编码在你的代码,所以每当您更改名称或位置IBar你需要更新其带点名称foo.py

2)标记的接口

另一种方法是让IFooIBar实现你保持在第三个文件,标志接口ns/content/interfaces.py例如。 这样,你可以做沿东西线

interfaces.py

from zope.interface import Interface

class IBarMarker(Interface):
    """Marker interface for IBar objects.
    """

class IFooMarker(Interface):
    """Marker interface for IFoo objects.
    """

foo.py

from zope.interface import directlyProvides
from plone.directives import form
from plone.formwidget.contenttree import ObjPathSourceBinder
from plone.formwidget.autocomplete import AutocompleteFieldWidget
from z3c.relationfield.schema import RelationChoice

from ns.content.interfaces import IBarMarker
from ns.content.interfaces import IFooMarker


class IFoo(form.Schema):
    directlyProvides(IFooMarker)

    form.widget(bar=AutocompleteFieldWidget)
    bar = RelationChoice(source=ObjPathSourceBinder(
                            object_provides=IBarMarker.__identifier__),
                         required=False)

bar.py

class IBar(form.Schema):
    directlyProvides(IBarMarker)

    form.widget(foo=AutocompleteFieldWidget)
    foo = RelationChoice(source=ObjPathSourceBinder(
                            object_provides=IFooMarker.__identifier__),
                         required=False)


文章来源: circular import references from zope schemas