[SOLVED] How to pass a parameter to an IQuerySource or IContextSourceBinder

I have a small pythonscript dispatcher that inserts a value in request.form and returns a form: class EDIOrderForm(AutoExtensibleForm, form.EditForm). In my EDIOrderForm, I have subclassed getContent and am prefilling the (Customer ID) value found in my request.form. So far, so good.

On the right side is a Choice field where the customer should be able to select from a filtered list of articles, based on theid Customer ID.

This does not work: I can't seem to pass on the customer id to either the binder or the source itself because the context, as seen by either, is not the form but a <NO_VALUE> object. What am I missing here?

line_item_article = schema.Choice(
    title    = _(
        'line_item_article_title',
        default=u'Article'
    ),
    required    = True,
    source = EDIOrderArticlesSourceBinder(),
)
directives.widget(
    'line_item_article',
    SelectFieldWidget,
    allowNewItems = False,
)

The binder is simply:

@implementer(IContextSourceBinder)
class EDIOrderArticlesSourceBinder(object):
    """ """
    def __call__(self, context):
        log.info('%s called with context: %s' % (self, context))
        return EDIOrderArticlesSource(context)

and the IQuerySource object returns the correct results when I hardcode the customer number.

Here's what I see in my log:

mypackage.browser.create_edi_order request.form passed to getContent: {'c_hash': 2744360}
mypackage.browser.create_edi_order customer hash: 2744360
mypackage.browser.create_edi_order widgets: None
mypackage.browser.create_edi_order request.form updated after getContent: {'c_hash': 2744360, 'customer_id': 'K 3080'}
mypackage.vocabularies.sources <mdb_mypackage.vocabularies.sources.EDIOrderArticlesSourceBinder object at 0x7fca2681ca90> called with context: <NO_VALUE>
mypackage.vocabularies.sources <mypackage.vocabularies.sources.EDIOrderArticlesSource object at 0x7fca10cb4490> called with context: <NO_VALUE>
mypackage.vocabularies.sources <mypackage.vocabularies.sources.EDIOrderArticlesSource object at 0x7fca10cb4490> is using customer_id: K 9169
[..]
mypackage.browser.create_edi_order request.form passed to getContent: {'c_hash': 2744360, 'customer_id': 'K 3080'}
mypackage.browser.create_edi_order customer hash: 2744360
mypackage.browser.create_edi_order widgets: <z3c.form.field.FieldWidgets object at 0x7fca27f491d0>
mypackage.browser.create_edi_order request.form updated after getContent: {'c_hash': 2744360, 'customer_id': 'K 3080'}

I'm not sure, but should the Binder implement ISource and provide IContextSourceBinder ?

@implementer(ISource)
@provider(IContextSourceBinder)
class YourBinder:
 .....

Edit: I initially misread your suggestion and made the source implement ISource and provide IContextSourceBinder. Fixing this resulted in the exact same traceback as below.

I had the source class as implementing IQuerySource

Your suggestion gives me a traceback:
ComponentLookupError: ((<NO_VALUE>, <HTTPRequest, URL=http://localhost:8585/mdb/api/edi-order>, <collective.z3cform.datagridfield.datagridfield.DataGridFieldObjectSubForm object at 0x7fac01d88f90>, <zope.schema._field.Choice object at 0x7fac17a35810>, <SelectWidget 'edi_order_form.widgets.order_data.AA.widgets.item_data.AA.widgets.line_item_article'>), , u'')

Full traceback:

Traceback (innermost last):
  Module ZPublisher.Publish, line 138, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 48, in call_object
  Module Shared.DC.Scripts.Bindings, line 322, in __call__
  Module Shared.DC.Scripts.Bindings, line 359, in _bindAndExec
  Module Products.PythonScripts.PythonScript, line 344, in _exec
  Module script, line 36, in edi-order
   - <PythonScript at /mdb/api/edi-order>
   - Line 36
  Module z3c.form.form, line 233, in __call__
  Module mdb_theme.browser.create_edi_order, line 99, in update
  Module plone.z3cform.fieldsets.extensible, line 65, in update
  Module plone.z3cform.patch, line 30, in GroupForm_update
  Module z3c.form.group, line 132, in update
  Module z3c.form.form, line 136, in updateWidgets
  Module z3c.form.field, line 277, in update
  Module z3c.form.browser.multi, line 63, in update
  Module z3c.form.browser.widget, line 171, in update
  Module z3c.form.widget, line 496, in update
  Module Products.CMFPlone.patches.z3c_form, line 47, in _wrapped
  Module z3c.form.widget, line 132, in update
  Module z3c.form.widget, line 491, in value
  Module collective.z3cform.datagridfield.datagridfield, line 177, in updateWidgets
  Module collective.z3cform.datagridfield.datagridfield, line 149, in getWidget
  Module z3c.form.browser.widget, line 171, in update
  Module z3c.form.object, line 217, in update
  Module collective.z3cform.datagridfield.datagridfield, line 311, in updateWidgets
  Module z3c.form.object, line 208, in updateWidgets
  Module collective.z3cform.datagridfield.datagridfield, line 439, in update
  Module plone.z3cform.fieldsets.extensible, line 65, in update
  Module plone.z3cform.patch, line 30, in GroupForm_update
  Module z3c.form.group, line 132, in update
  Module collective.z3cform.datagridfield.datagridfield, line 446, in updateWidgets
  Module z3c.form.form, line 136, in updateWidgets
  Module z3c.form.field, line 277, in update
  Module z3c.form.browser.multi, line 63, in update
  Module z3c.form.browser.widget, line 171, in update
  Module z3c.form.widget, line 496, in update
  Module Products.CMFPlone.patches.z3c_form, line 47, in _wrapped
  Module z3c.form.widget, line 132, in update
  Module z3c.form.widget, line 491, in value
  Module collective.z3cform.datagridfield.datagridfield, line 177, in updateWidgets
  Module collective.z3cform.datagridfield.datagridfield, line 149, in getWidget
  Module z3c.form.browser.widget, line 171, in update
  Module z3c.form.object, line 217, in update
  Module collective.z3cform.datagridfield.datagridfield, line 311, in updateWidgets
  Module z3c.form.object, line 208, in updateWidgets
  Module collective.z3cform.datagridfield.datagridfield, line 439, in update
  Module plone.z3cform.fieldsets.extensible, line 65, in update
  Module plone.z3cform.patch, line 30, in GroupForm_update
  Module z3c.form.group, line 132, in update
  Module collective.z3cform.datagridfield.datagridfield, line 446, in updateWidgets
  Module z3c.form.form, line 136, in updateWidgets
  Module z3c.form.field, line 277, in update
  Module z3c.form.browser.select, line 51, in update
  Module z3c.form.browser.widget, line 171, in update
  Module z3c.form.widget, line 233, in update
  Module z3c.form.widget, line 227, in updateTerms
  Module zope.component._api, line 112, in getMultiAdapter
ComponentLookupError: ((<NO_VALUE>, <HTTPRequest, URL=http://localhost:8585/mdb/api/edi-order>, <collective.z3cform.datagridfield.datagridfield.DataGridFieldObjectSubForm object at 0x7fac01d88f90>, <zope.schema._field.Choice object at 0x7fac17a35810>, <SelectWidget 'edi_order_form.widgets.order_data.AA.widgets.item_data.AA.widgets.line_item_article'>), <InterfaceClass z3c.form.interfaces.ITerms>, u'')

as much as I hate to say it: this helped me...


@implementer(IContextSourceBinder)
class EDIOrderArticlesSourceBinder(object):
    """ """
    def __call__(self, context):
        log.info('%s called with context: %s' % (self, context))
        request = getRequest()
        log.info('form value: %s' % request.get('customer_id','nothing'))        
        return EDIOrderArticlesSource(context)

mdb_theme.vocabularies.sources <mdb_theme.vocabularies.sources.EDIOrderArticlesSourceBinder object at 0x7fdf3fdd0810> called with context: <NO_VALUE>
mdb_theme.vocabularies.sources form value: K 3080

1 Like