Overview
Autocomplete filters provide a search-enabled filtering interface that loads options dynamically via AJAX. This makes them perfect for filtering by fields with large datasets (hundreds or thousands of options) where standard dropdowns would be impractical.
Autocomplete filters require the related model to have an admin class registered with search_fields defined.
Available Autocomplete Filters
AutocompleteSelectFilter Single selection with search for related fields
AutocompleteSelectMultipleFilter Multiple selection with search for related fields
AutocompleteSelectFilter
Filter by a single related object with search capabilities.
Basic Setup
Configure the related model admin
The related model must have search_fields defined: from django.contrib import admin
from unfold.admin import ModelAdmin
from .models import Author
@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
search_fields = [ "first_name" , "last_name" , "email" ]
Add autocomplete filter to your model
from unfold.contrib.filters.admin import AutocompleteSelectFilter
from .models import Book
@admin.register (Book)
class BookAdmin ( ModelAdmin ):
list_filter = [
( "author" , AutocompleteSelectFilter),
]
Complete Example
from django.db import models
class Author ( models . Model ):
first_name = models.CharField( max_length = 100 )
last_name = models.CharField( max_length = 100 )
email = models.EmailField( unique = True )
def __str__ ( self ):
return f " { self .first_name } { self .last_name } "
class Book ( models . Model ):
title = models.CharField( max_length = 200 )
author = models.ForeignKey(Author, on_delete = models. CASCADE )
published_date = models.DateField()
def __str__ ( self ):
return self .title
from django.contrib import admin
from unfold.admin import ModelAdmin
from unfold.contrib.filters.admin import AutocompleteSelectFilter
from .models import Author, Book
@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
search_fields = [ "first_name" , "last_name" , "email" ]
list_display = [ "first_name" , "last_name" , "email" ]
@admin.register (Book)
class BookAdmin ( ModelAdmin ):
list_display = [ "title" , "author" , "published_date" ]
list_filter = [
( "author" , AutocompleteSelectFilter),
]
Users can now type in the filter to search authors by first name, last name, or email.
AutocompleteSelectMultipleFilter
Filter by multiple related objects with search.
class Tag ( models . Model ):
name = models.CharField( max_length = 50 , unique = True )
def __str__ ( self ):
return self .name
class Article ( models . Model ):
title = models.CharField( max_length = 200 )
tags = models.ManyToManyField(Tag)
published = models.BooleanField( default = False )
from unfold.contrib.filters.admin import AutocompleteSelectMultipleFilter
@admin.register (Tag)
class TagAdmin ( ModelAdmin ):
search_fields = [ "name" ]
@admin.register (Article)
class ArticleAdmin ( ModelAdmin ):
list_display = [ "title" , "published" ]
list_filter = [
( "tags" , AutocompleteSelectMultipleFilter),
]
Users can select multiple tags to filter articles. The filter uses an AND logic by default (articles must have all selected tags).
Search Configuration
Case-Insensitive Search
Use __icontains or __istartswith lookups:
@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
search_fields = [
"first_name__icontains" ,
"last_name__icontains" ,
]
Search across relationships:
@admin.register (Book)
class BookAdmin ( ModelAdmin ):
search_fields = [
"title" ,
"author__first_name" , # Search by author's first name
"author__last_name" , # Search by author's last name
]
list_filter = [
( "author" , AutocompleteSelectFilter),
]
Customize Search Terms
@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
search_fields = [ "first_name" , "last_name" , "email" ]
def get_search_results ( self , request , queryset , search_term ):
queryset, use_distinct = super ().get_search_results(
request, queryset, search_term
)
# Add custom search logic
if search_term:
# Example: Search by full name
queryset |= self .model.objects.filter(
first_name__icontains = search_term.split()[ 0 ] if search_term else ""
)
return queryset, use_distinct
Advanced Configuration
Minimum Search Length
You can configure minimum characters required before search triggers:
from unfold.contrib.filters.admin import AutocompleteSelectFilter
class CustomAutocompleteFilter ( AutocompleteSelectFilter ):
# Customize form to set minimum input length
class Media :
js = ( 'admin/js/custom-autocomplete.js' ,)
Custom Empty Label
class CustomAutocompleteFilter ( AutocompleteSelectFilter ):
def choices ( self , changelist ):
for choice in super ().choices(changelist):
# Customize the form
form = choice[ 'form' ]
# Add custom empty label or placeholder
yield choice
Limit Results
Control the number of autocomplete results:
@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
search_fields = [ "first_name" , "last_name" ]
def get_search_results ( self , request , queryset , search_term ):
queryset, use_distinct = super ().get_search_results(
request, queryset, search_term
)
# Limit to 10 results
return queryset[: 10 ], use_distinct
Filtering ManyToManyField
For many-to-many relationships:
class Category ( models . Model ):
name = models.CharField( max_length = 100 )
def __str__ ( self ):
return self .name
class Product ( models . Model ):
name = models.CharField( max_length = 200 )
categories = models.ManyToManyField(Category)
from unfold.contrib.filters.admin import AutocompleteSelectMultipleFilter
@admin.register (Category)
class CategoryAdmin ( ModelAdmin ):
search_fields = [ "name" ]
@admin.register (Product)
class ProductAdmin ( ModelAdmin ):
list_filter = [
( "categories" , AutocompleteSelectMultipleFilter),
]
With Faceted Counts
Autocomplete filters support faceted counts, but they only show after a selection is made (not during search).
from django.contrib import admin
from unfold.admin import ModelAdmin
from unfold.contrib.filters.admin import AutocompleteSelectFilter
@admin.register (Book)
class BookAdmin ( ModelAdmin ):
show_facets = admin.ShowFacets. ALWAYS
list_filter = [
( "author" , AutocompleteSelectFilter),
]
Permissions
Restrict Autocomplete Access
Control who can see autocomplete results:
@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
search_fields = [ "first_name" , "last_name" ]
def has_view_permission ( self , request , obj = None ):
# Only staff with view permission can search
return request.user.has_perm( 'myapp.view_author' )
Field-Level Permissions
@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
search_fields = [ "first_name" , "last_name" , "email" ]
def get_search_fields ( self , request ):
# Hide email from search for non-superusers
if request.user.is_superuser:
return self .search_fields
return [ "first_name" , "last_name" ]
Add indexes to fields used in search_fields: class Author ( models . Model ):
first_name = models.CharField( max_length = 100 , db_index = True )
last_name = models.CharField( max_length = 100 , db_index = True )
email = models.EmailField( unique = True ) # Already indexed
Use select_related() and prefetch_related(): @admin.register (Book)
class BookAdmin ( ModelAdmin ):
list_filter = [( "author" , AutocompleteSelectFilter)]
def get_queryset ( self , request ):
return super ().get_queryset(request).select_related( 'author' )
Troubleshooting
Problem : Filter shows but autocomplete doesn’t trigger.Solution : Ensure the related model admin has search_fields defined:@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
search_fields = [ "first_name" , "last_name" ] # Required!
Problem : Search returns no results even though data exists.Solution : Check that:
search_fields contains the correct field names
Fields are searchable (CharField, TextField, etc.)
User has permission to view the related model
Database contains matching records
Problem : Users get permission errors when using autocomplete.Solution : Ensure users have view permission for the related model:@admin.register (Author)
class AuthorAdmin ( ModelAdmin ):
def has_view_permission ( self , request , obj = None ):
return request.user.has_perm( 'myapp.view_author' )
API Reference
AutocompleteSelectFilter
The model field to filter on (passed automatically in tuple format)
form_class
type
default: "AutocompleteDropdownForm"
Form class used for rendering the autocomplete widget
template
str
default: "\"unfold/filters/filters_field.html\""
Template used to render the filter
Requirements
The related model must have:
An admin class registered
search_fields defined
View permissions for the user
Best Practices
Use for large datasets
Autocomplete filters are ideal when you have >50 options. For fewer options, consider dropdown filters.
Optimize search fields
Index searchable fields in the database
Use specific field lookups (__istartswith vs __icontains)
Limit the number of fields in search_fields
Provide clear __str__ methods
Ensure related models have descriptive __str__ methods: def __str__ ( self ):
return f " { self .first_name } { self .last_name } ( { self .email } )"
Next Steps
Dropdown Filters Learn about standard dropdown filters for smaller datasets
Text Filters Explore free-text search filters