2

参加者と基準の 2 つの Dexterity コンテンツ タイプがあります。後者は、プロジェクトへの参加者の参加を決定するために使用されます。基準はRelationListとして Participant に保存されますが、デフォルトのピッカー ウィジェットをチェックボックス ベースのウィジェットに置き換えたいと考えています。正しい基準をチェックボックスとして表示する基準フィールドに割り当てるカスタム ウィジェットを作成しましたが、検証時に次のエラーが表示されます。

2011-11-04 00:27:26 ERROR Zope.SiteErrorLog 1320380846.610.720672558798 http://192.168.2.128:8080/ctcc/Trials/trial1/sites/site1/++add++ctcc.Participant
Traceback (innermost last):
  Module ZPublisher.Publish, line 126, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 46, in call_object
  Module plone.z3cform.layout, line 70, in __call__
  Module plone.z3cform.layout, line 54, in update
  Module plone.z3cform.fieldsets.extensible, line 59, in update
  Module plone.z3cform.patch, line 30, in GroupForm_update
  Module z3c.form.group, line 125, in update
  Module z3c.form.form, line 134, in updateWidgets
  Module z3c.form.field, line 275, in update
  Module z3c.form.browser.checkbox, line 44, in update
  Module z3c.form.browser.widget, line 70, in update
  Module z3c.form.widget, line 200, in update
  Module z3c.form.widget, line 84, in update
  Module z3c.form.widget, line 216, in extract
AttributeError: 'list' object has no attribute 'getTermByToken'

私は次のようにウィジェットを定義しました:

class ICriteriaListingWidget(Interface):
    """Marker interface for the criteria listing widget"""

class CriteriaSelectionWidget(CheckBoxWidget):
    implements(ICriteriaListingWidget)
    klass = u'criteria-listing-widget'
    input_template = ViewPageTemplateFile('criteria_listing_input.pt')
    display_template = ViewPageTemplateFile('criteria_listing_display.pt')

    @property
    def terms(self):
        catalog = getToolByName(self.context, 'portal_catalog')
        content = catalog(
            portal_type='ctcc.Criterion',
        )
        return [SimpleTerm(x.id, x, title=x.Title) for x in content]

@adapter(IRelationList, IFormLayer)
@implementer(IFieldWidget)
def CriteriaListingWidget(field, request):
    return FieldWidget(field, CriteriaSelectionWidget(request))

次に、参加者の器用さタイプでは、フィールドは次のとおりです。

form.widget(criteria=CriteriaListingWidget)
criteria = RelationList(
    title = _(u'Inclusion Criteria'),
    description = _(u'The participant criteria evaluated against for inclusion'),
    value_type = RelationChoice(
        source = ObjPathSourceBinder(
            object_provides = ICriterion.__identifier__,
        ),
    ),
    default = [],
    required = False,
)

エラーの性質を考慮して、ObjPathSourceBinderソースを基準のカスタム語彙に置き換えて、正しいインターフェイスを持つオブジェクトを返すことを望んでいましたが、そのソリューションを使用してもまったく同じエラーが発生しています。

更新:提案されているように、SimpleVocabulary で用語リストをラップしましたが、問題がシフトするだけです。kss_z3cform_inline_validationでエラーが発生していることに注意してください。

2011-11-06 19:24:36 ERROR Zope.SiteErrorLog 1320625476.430.209960132592 http://192.168.2.128:8080/ctcc/Trials/trial1/sites/site1/kss_z3cform_inline_validation
Traceback (innermost last):
  Module ZPublisher.Publish, line 126, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 46, in call_object
  Module <wrapper>, line 5, in wrapper
  Module kss.core.actionwrapper, line 236, in apply
  Module plone.app.z3cform.kss.validation, line 51, in validate_input
  Module z3c.form.group, line 92, in extractData
  Module z3c.form.form, line 145, in extractData
  Module z3c.form.field, line 301, in extract
  Module z3c.form.converter, line 311, in toFieldValue
AttributeError: 'SimpleVocabulary' object has no attribute 'getValue'
2011-11-06 19:24:36 ERROR plone.transformchain Unexpected error whilst trying to apply transform chain
4

2 に答える 2

3

リストではなく、語彙オブジェクトを返す必要があります。

from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary

# ...

class CriteriaSelectionWidget(CheckBoxWidget):
    # ...

    @property
    def terms(self):
        catalog = getToolByName(self.context, 'portal_catalog')
        content = catalog(
            portal_type='ctcc.Criterion',
        )
        return SimpleVocabulary([SimpleTerm(x.id, x, title=x.Title) for x in content])

このSimpleVocabulary場合、クラスは正しいメソッドを実装します。

于 2011-11-04T06:59:42.927 に答える
1

これ自体が答えとしてカウントされるかどうかはわかりませんが、カスタム Source および SourceBinder オブジェクトを作成することで、カスタム ウィジェットの必要性を回避することになりました。

class CTCCSource(object):
    implements(IVocabularyTokenized)

    container    = None
    content_type = None

    def __init__(self, context):
        self.context = context
        container_path = self._container_path(context)
        self.catalog = getToolByName(context, 'portal_catalog')
        self.intid_utility = getUtility(IIntIds)
        self.content = [i.getObject() for i in self.catalog(portal_type=self.content_type, path={'query': container_path})]

    def _container_path(self, context):
        physical_path = list(context.getPhysicalPath())
        trial_path = physical_path[:physical_path.index('sites')]
        criteria_path = trial_path + [self.container]
        return '/'.join(criteria_path)

    def __contains__(self, term):
        return term in self.content

    def __iter__(self):
        for crit in self.content:
            yield SimpleTerm(crit, self.intid_utility.getId(crit), crit.Title)

    def __len__(self):
        return len(self.content)

    def getTerm(self, obj):
        return SimpleVocabulary.createTerm(
            obj, self.intid_utility.getId(obj), obj.Title()
        )

    def getTermByToken(self, value):
        return self.getTerm(self.intid_utility.getObject(int(value)))

class CTCCSourceBinder(object):
    implements(IContextSourceBinder)
    source = None

    def __init__(self, **kw):
        pass

    def __call__(self, context):
        return self.source(context)

これにより、現在のコンテキストに含まれるコンテンツからフォーム チェックボックス フィールドを作成し、選択したオプションへの参照を RelatedList に追加することができました。

于 2011-11-16T07:11:26.917 に答える