django admin when field is autocomplete it overrides ModelForm filter

having issue on django admin. I want one of my foreign key field to be searchable and I achieved that making it autocomplete.

class CollectionAdmin(VersionAdmin, admin.ModelAdmin):
    form = CollectionForm
    autocomplete_fields = ["task"]

I also filter that foreign key in ModelForm.

class CollectionForm(forms.ModelForm):
    class Meta:
        model = Collection
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if self.fields.get("task"):
            self.fields["task"].queryset = self.fields["task"].queryset.filter(
                status=TaskStatus.ASSIGNED
            )

When task is not autocomplete field in Collection my filter works as expected. However, when task is autocomplete field in Collection, filter does not work. Instead of my filter in form, task admin get_queryset method is called which is not what I want.

TaskAdmin get_queryset method just filters by user, however I want more filter as you see above, for TaskStatus as well.

def get_queryset(self, request):
    qs = super().get_queryset(request)
    if request.user.groups.filter(name=settings.COPYWRITER_GROUP).exists():
        return qs.filter(assigned_to=request.user)
    return qs

Repeating, form init filter works if field is not autocomplete.

I tried removing task from autocomplete of Collection and it worked. I want my form filter not overridden if field is autocomplete.

The autocomplete_fields use different logic because it’s built on the JavaScript Select2 library.

See the docs at autocomplete_fields.

No, they don’t work the same, no, you can’t make it work the same, and yes, if you want to customize the results, you need to work with how it works.

Also see get_search_results.

There was also this conversation here in the forum: Django Admin Autocomplete Field Search Customization

1 Like

Hello KenWhitesell,
Thank you for your comment, I really appreciate your help.

Answering my own question. When you make field autocomplete, it directly triggers get_queryset method of that model admin. So, in my case, TaskAdmin get_queryset is called each time when I try to select value from dropdown. That is why, form filter became useless, we can actually totally remove that filter. Workaround is to conditionally filtering objects in TaskAdmin get_queryset. I am providing example,

    path = request.path
    if "autocomplete" in path:
        return super().get_queryset(request).filter()
    else:
        return super().get_queryset(request)

This will filter queryset if it is called from dropdown. Thansk!