django-autocomplete-light
django-autocomplete-light copied to clipboard
ListSelect2 widget: 'CallableChoiceIterator' object has no attribute 'insert'
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.
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, ""))
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.