circular import references from zope schemas

后端 未结 1 1751
闹比i
闹比i 2021-01-25 19:37

i\'m having a problem very similar to this SO question, but my attempts to apply these previous answers isn\'t going thru and it was suggested i start it as a new question:

相关标签:
1条回答
  • 2021-01-25 20:21

    You're calling getBarChoices() at definition time, when defining the class IFoo. So from bar import IBar will be executed while parsing foo.py leading to the circular import.

    As far as I see it, you have basically two choices:

    1) Use a string as identifier for object_provides.

    You're doing that already anyway by using IFoo.__identifier__, but if you make it static instead of dynamic that will eliminate your circular dependencies:

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

    No need to import IBar in foo.py. This has the obvious disadvantage that the location of IBar is now hardcoded in your code, so whenever you change the name or location of IBar you'll need to update its dotted name in foo.py.

    2) Marker interfaces

    The other alternative would be to let IFoo and IBar implement marker interfaces that you keep in a third file, ns/content/interfaces.py for example. That way you could do something along the lines of

    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)
    
    0 讨论(0)
提交回复
热议问题