Search code examples
djangodjango-autocomplete-light

Django Autocomplete Light: multiple selection from List (not Model)


I know how to use DAL (Django Autocomplete Light) to allow a single selection from a list, like in the tutorial:

CHOICE_LIST = [
        ['FR', 'France'],
        ['FJ', 'Fiji'],
        ['FI', 'Finland'],
        ['CH', 'Switzerland']
    ]

class CountryAutocompleteFromList(autocomplete.Select2ListView):
    def get_list(self):
        return CHOICE_LIST

class CountryForm(forms.ModelForm):
    country = autocomplete.Select2ListChoiceField(
        choice_list=CHOICE_LIST,
        widget=autocomplete.ListSelect2(url='country-list-autocomplete')
    )

However, I can't find any lead in the documentation or DAL source code to implement multiple selection, e.g. to allow users to pick 2 countries or more, in combination with django.contrib.postgres.fields import ArrayField which I already use in my code.

Has anyone a working example I could learn from?


Solution

  • After a long period of trial and error, the following works.

    Say you want to ask a list of emails, optionally with some autocompletion, but also being able to create/add new ones on the fly

    class Select2ListCreateMultipleChoiceField(Select2ListCreateChoiceField, Select2Multiple):
        def to_python(self, value):
            if not value:
                return []
            elif not isinstance(value, list):
                return [value]
            return value
    
        def validate(self, value):
            # for create :
            super(ChoiceField, self).validate(value)
            # otherwise you could use :
            # for v in value:
            #     super().validate(v)
    
        def bound_data(self, data, initial):
            if self.disabled:
                return initial
            return data
    
    
    class ListSelect2Multiple(WidgetMixin, Select2WidgetMixin, forms.SelectMultiple):
        """Select widget for regular choices and Select2."""
    
    
    class EmailsForm(forms.Form):
        emails = Select2ListCreateMultipleChoiceField(
            label="Emails",
            help_text="Emails list",
            widget=ListSelect2Multiple(
                url='........ your view name for autocompletion .......',
            ),
        )
    

    You can then use EmailsForm(request.POST).cleaned_data normally afterward and save it however you'd like.