Searchable drop down for choice field in django admin
Asked Answered
S

1

5

I have a choice field with lot's of data, I have created drop down at admin panel but I want to have a searchable drop down.

class ItemForm(forms.ModelForm):

   def __init__(self, *args, **kwargs):
       super(PublicUserForm, self).__init__(*args, **kwargs)
       self.fields['city'] = forms.ChoiceField(
       choices = CHOOSE_CITY) 

class ItemAdmin(admin.ModelAdmin):
   form = ItemForm

admin.site.register(Item, ItemAdmin)

I have reffered django-autocomplete-light.

Thanks in advance!

Soandso answered 21/6, 2018 at 5:13 Comment(0)
L
6

Follow these steps

Install django autocomplete light using pip

pip install django-autocomplete-light

Then, to let Django find the static files we need by adding to INSTALLED_APPS, before django.contrib.admin and grappelli if present

'dal',
'dal_select2',
#'grappelli',
'django.contrib.admin',

Now You need to create an autocomplete view that will respond with filtered queryset when you search.

from dal import autocomplete

from your_app.models import City


class CityAutocomplete(autocomplete.Select2QuerySetView):
    def get_queryset(self):

        if not self.request.user.is_authenticated:
            return City.objects.none()

        qs = City.objects.all()

        if self.q:
            qs = qs.filter(name__istartswith=self.q)

        return qs

Note: The base view for autocomplete view should be Select2QuerySetView.

Now register the autocomplete view Create a named url for the view

from your_app.views import CityAutocomplete

urlpatterns = [
    url(
        r'^city-autocomplete/$',
        CityAutocomplete.as_view(),
        name='city-autocomplete',
    ),
]

You can now use the autocomplete view in Item form. use ModelSelect2 to create widget

from dal import autocomplete

from django import forms


class ItemForm(forms.ModelForm):
    city = forms.ModelChoiceField(
        queryset=City.objects.all(),
        widget=autocomplete.ModelSelect2(url='city-autocomplete')
    )

    class Meta:
        model = Item
        fields = ('__all__')

Now you can easily use it in admin.

from your_app.forms import ItemForm

class ItemAdmin(admin.ModelAdmin):
   form = ItemForm

admin.site.register(Item, ItemAdmin)

Note: This will work if you have city field as a foreign key in the Item model.


If city is a Choice field you can use autocompleting based on a list of Strings

Create a listview using Select2ListView and override get_list method

class CityAutocomplete(autocomplete.Select2ListView):
    def get_list(self):
        # return all cities name here, it will be auto filtered by super class
        return ['Pune', 'Patna', 'Mumbai', 'Delhi', ...]

Register URL as above, now modify your model form and use Select2ListChoiceField

def get_choice_list():
    # all cites to used as chice list
    return ['Pune', 'Patna', 'Mumbai', 'Delhi', ...]


class ItemForm(forms.ModelForm):
    city = autocomplete.Select2ListChoiceField(
        choice_list=get_choice_list,
        widget=autocomplete.ListSelect2(url='city-autocomplete')
    )

    class Meta:
        model = Item
        fields = ('__all__')

Add this form to ModelAdmin as we did in above example.

Linalool answered 21/6, 2018 at 5:50 Comment(5)
I have to use ChoiceField not ModelChoiceField . I have tried self.fields['slack_channel'] = forms.ChoiceField( choices = get_my_choices(), widget=autocomplete.Select2(url='choose_channel') ) but i am not getting 'q' from adminSoandso
if city is a field in your Item model you can user ModelChoiceField while creating formLinalool
Also use ModelSelect2 not Select2 in widgetLinalool
@Linalool you have an error in your code - there should be no invokation of "is_authenticated" in the view, it should just be - if not self.request.user.is_authenticated - otherwise you will gett "bool object is not callable"Spinozism
@Spinozism Yes exactly. Thanks for the heads up. updated the answer.Linalool

© 2022 - 2024 — McMap. All rights reserved.