1

私はこの SO questionと非常によく似た問題を抱えていますが、これらの以前の回答を適用しようとしてもうまくいかず、新しい質問として開始することが提案されました:

以下のコードでは、循環参照を延期すると思われるいくつかの 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
"""
4

1 に答える 1

4

getBarChoices()class を定義するときに、定義時に呼び出していますIFoo。そのため、循環インポートにつながるfrom bar import IBar解析中に実行されます。foo.py

私が見る限り、基本的に 2 つの選択肢があります。

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) マーカーインターフェース

もう 1 つの方法は、たとえば、3 番目のファイルに保持するマーカー インターフェイスを許可IFooして実装することです。そうすれば、次のようなことができますIBarns/content/interfaces.py

インターフェイス.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)
于 2012-09-05T17:48:03.723 に答える