Plone 5.2.1/plone.formwidget.autocomplete - How can I get AutocompleteFieldWidget to work with my Plone 5.2.1 installation?

I have a Plone 5.2.1 site and I'm trying to use the AutocompleteFieldWidget for an autocomplete choice field and unfortunately I'm having trouble getting it to work.

My interface in food.py:

from zope import schema
from plone.autoform import directives as form
from plone.supermodel import model   
from plone.formwidget.autocomplete import AutocompleteFieldWidget
from my.product.dummyvocab import FoodTypeVocabulary

class IFood(model.Schema):
    
    form.widget('foodtype',AutocompleteFieldWidget)
    foodtype = schema.Choice(title=_(u"Food Type"),
                             source=FoodTypeVocabulary(),
                             )

My vocabulary source in dummyvocab.py:

from z3c.formwidget.query.interfaces import IQuerySource
from zope.interface import implements
from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleTerm

terms = ['Poultry','Pork','Fish','Vegetables','Fruit','Beverage',]

class FoodTypeVocabularySource(object):
    implements(IQuerySource)
    
    def __init__(self, context):
        self.context = context

    def __contains__ (self, term):
        for i in terms:
            if term == i:
                return SimpleTerm(title=i,token=i,value=i)
        return None

    def getTerm(self, value):
        if value is None:
            return None
        for i in terms:
            if i == value:
                return SimpleTerm(title=i, token=i, value = i)
        
    def getTermByToken(self, token):
        return getTerm(token)

    def search(self, query_string):
        results = []
        for i in terms:
            if query_string in i:
                results.append(SimpleTerm(title=i,token=i,value=i))
        return results

class FoodTypeVocabulary(object):
    implements(IContextSourceBinder)

    def __call__(self, context):
        return FoodTypeVocabularySource

When I load the page, I get a recursive error.

  Module ZPublisher.WSGIPublisher, line 156, in transaction_pubevents
  Module ZPublisher.WSGIPublisher, line 338, in publish_module
  Module ZPublisher.WSGIPublisher, line 256, in publish
  Module ZPublisher.mapply, line 85, in mapply
  Module ZPublisher.WSGIPublisher, line 62, in call_object
  Module plone.z3cform.layout, line 63, in __call__
  Module plone.z3cform.layout, line 47, in update
  Module plone.dexterity.browser.add, line 141, in update
  Module plone.z3cform.fieldsets.extensible, line 64, in update
  Module plone.autoform.form, line 34, in updateFields
  Module plone.autoform.base, line 67, in updateFieldsFromSchemata
  Module plone.dexterity.browser.base, line 25, in schema
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 406, in __call__
  Module plone.dexterity.fti, line 281, in lookupModel
  Module plone.dexterity.fti, line 269, in lookupSchema
  Module plone.alterego.dynamic, line 29, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
RuntimeError: maximum recursion depth exceeded while calling a Python object

Also, the version of plone.formwidget I'm is 1.4.0. Unfortunately for some reason the earlier version I was working with didn't import its javascript files when it was installed.

Is it my source that is causing the error or am I approaching how I use the Autocomplete in my interface wrong?

first, use the decorator in 5.2.1

@implementer(IContextSourceBinder)
class FoodTypeVocabulary(object):
    def __call__(self, context):
        return FoodTypeVocabularySource
1 Like

This is only needed for Python 3, but yes.
We also had issues with the autocomplete widget in Plone 5.2, Python 3 and dropped its usage for now.

1 Like

This render a select2-widget with autocomplete behavior. but the autocomplete-property only works for me with a schema.Choice not with a schema.List Field.

from plone.autoform import directives
from plone.app.z3cform.widget import SelectFieldWidget

class IMyContenttype(model.Schema):

    area = schema.Choice(
        title = 'Area',
        missing_value='',
        required = True,
        vocabulary="mf.areas"
    )
    
    directives.widget(
        'area',
        SelectFieldWidget,
        vocabulary='mf.areas'
    )
2 Likes

Unfortunately, I'm having trouble with using Python 3 with Plone in general (ZMI breaks with python 3.6.9), but I'll keep this in mind. Thanks for letting me know about autocomplete's current compatibility status with Plone 5.2.

Thank you. I never used SelectFieldWidget before and it seems to work with a straightforward simple vocabulary.

In dummyvocab.py

def food_types(context):
    return SimpleVocabulary([SimpleTerm(value=i,token=i, title=i) for i in terms])

In configure.zcml

<utility
    provides="zope.schema.interfaces.IVocabularyFactory"
    component="my.product.dummyvocab.food_types"
    name="my-food-types"
    />

In food.py:

form.widget('foodtype', SelectFieldWidget, vocabulary='my-food-types')
foodtype = schema.Choice(title=_(u"Food type"),
                    missing_value='',
                    required=True,
                    vocabulary='my-food-types'
                  ) 

It doesn't break and saves the values.

EDIT: I was able to get a list of choices made to work, as opposed to a filteration of a list though:

form.widget('foodtype', SelectFieldWidget)
foodtype = schema.List(title=u"Food Type",
                       value_type=schema.Choice(title=_(u"Food Type"),
                                                missing_value='',
                                                required=True,
                                                vocabulary='my-food-types'
                                                )
                       )

The main difference is I didn't use the 'vocabulary' parameter in directives.widget

I have to see how it can work with my vocabulary source.