django-autocomplete-light icon indicating copy to clipboard operation
django-autocomplete-light copied to clipboard

ListSelect2 widget: 'CallableChoiceIterator' object has no attribute 'insert'

Open tomsimonart opened this issue 6 years ago • 2 comments
trafficstars

Issue:

(python==3.7.4, django==2.2 and django-autocomplete-light==3.4.1) 'CallableChoiceIterator' object has no attribute 'insert' when using the ListSelect2 widget with a data-placeholder and a callable as list generator for a Select2ListChoiceField field in a form rendered in the django admin add/change view.

How to reproduce:

With the following example in the admin.py file

def my_callable():
    return [data for data in dataset] + [""]  # Adding empty choice to the generated list

class MyForm(forms.ModelForm):
    my_field = autocomplete.Select2ListChoiceField(
        choice_list=my_callable,
        widget=dal_widgets.ListSelect2(
            attrs={'data-placeholder': 'my placeholder'}
        ),
        required=False
    )
    
    class Meta:
        model = MyModel
        fields = [
            "my_field",
        ]

I get the following error while loading my view:

/home/me/myproject/venv/lib/python3.7/site-packages/dal/widgets.py", line 143, in optgroups self.choices.insert(0, (None, "")) AttributeError: 'CallableChoiceIterator' object has no attribute 'insert'

What's to be fixed

I assume some method on CallableChoiceIterator needs to be ran before trying to list.insert in it? https://github.com/yourlabs/django-autocomplete-light/blob/10affe2a82aa8007d9d4023908a8470404612203/src/dal/widgets.py#L120-L122

If it's my code that's messed up don't hesitate to tell me :slightly_smiling_face:

Also the widget is working perfectly fine without placeholder.

tomsimonart avatar Oct 18 '19 08:10 tomsimonart

Does it work if you disable self.placeholder to prevent the choices.insert call from happening ?

We could maybe check that self.choices has an insert method prior to calling it, ie. if hasattr(self.choices, 'insert'): self.choices.insert(0, (None, ""))

jpic avatar Nov 22 '19 12:11 jpic

I've been using DAL for awhile now (love it!) and had been using data-placeholder with Select2ListChoiceField and List2Select without any issues on Python 3.8.8, Django 3.2.9, and DAL 3.8.2. Oddly, the versions where I didn't see this bug are higher than the initial issue reporter's.

Without any changes to my forms or anything DAL-related, I got this exact issue after upgrading my stack to Python 3.8.12, Django 4.0.4, and DAL 3.9.4.

In my case, it was a non-admin form. Same error, same line, same fix. data-placeholder attribute for forms.ModelChoiceField with widget=dal.ModelSelect2() with a data-placeholder attribute does not cause this error.

I've worked around it by setting defaults that exist in the list elsewhere, rather than use a placeholder. Commenting out my data-placeholder attributes for only the List2Select widgets quickly resolved the exception.

Edit: I should add, in my case, it wasn't a callable. It was just lists that for some reason couldn't be inserted into..., e.g.:

tax_ranks = ["Kingdom", "Phylum", "Class", "Order", "Family", "Genus", "Species","Full"]
taxonomic_level = autocomplete.Select2ListChoiceField(choice_list=tax_ranks,
                                                      widget=autocomplete.ListSelect2(attrs={"style": "flex-grow: 1",
                                                                                             'data-placeholder': 'Genus',
                                                                                             'data-html': True}))

causes this exception for me. Resolved by commenting out 'data-placeholder' line.

mwhall avatar May 19 '22 16:05 mwhall