Learn how to build advanced Django admin filters with Unfold using text inputs, dropdowns, multiple selections, numeric and date ranges, autocomplete, checkboxes, radio buttons, and custom layouts.
Filtering is one of the most important parts of a useful Django admin interface. Once a changelist contains hundreds or thousands of records, users need more than a search box and a few basic links to find the data they need quickly.
Django Unfold extends the standard Django admin filtering system with reusable filters for text inputs, dropdowns, multiple selections, numeric ranges, date and datetime ranges, autocomplete fields, checkboxes, radio buttons, and custom filter layouts.
The filters still use Django's familiar ModelAdmin.list_filter configuration, so they can be introduced gradually without replacing the existing admin architecture.
In this guide, we will look at the filter options available in Unfold and how to choose the right one for different admin workflows.
Advanced filters are provided by the optional unfold.contrib.filters application.
Add it immediately after unfold in INSTALLED_APPS:
# settings.py
INSTALLED_APPS = [
"unfold",
"unfold.contrib.filters",
"django.contrib.admin",
# ...
]
Your admin classes should inherit from Unfold's ModelAdmin:
from django.contrib import admin
from unfold.admin import ModelAdmin
from .models import Order
@admin.register(Order)
class OrderAdmin(ModelAdmin):
pass
Filters are then configured through the normal list_filter option.
For filters containing input fields, such as text, numeric, or date ranges, enable the filter submit button:
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter_submit = True
This adds a submit button to the filter form so users can enter several values before applying them.
See the Unfold filters documentation for the complete reference.
Text filters are useful when users need to filter a changelist by a specific text field instead of using the global Django admin search box.
Unfold provides FieldTextFilter for the common case where a text input should filter a model field using a case-insensitive lookup.
from django.contrib import admin
from unfold.admin import ModelAdmin
from unfold.contrib.filters.admin import FieldTextFilter
from .models import Order
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter_submit = True
list_filter = [
("number", FieldTextFilter),
]
This works well for fields such as:
For more advanced query logic, Unfold also provides TextFilter, which can be subclassed and given a custom queryset() implementation.
from django.core.validators import EMPTY_VALUES
from django.utils.translation import gettext_lazy as _
from unfold.contrib.filters.admin import TextFilter
class CustomerSearchFilter(TextFilter):
title = _("Customer")
parameter_name = "customer"
def queryset(self, request, queryset):
if self.value() not in EMPTY_VALUES:
return queryset.filter(customer__name__icontains=self.value())
return queryset
This keeps the Unfold text-input UI while allowing the filtering logic to span relationships or use custom ORM expressions.
Read more in the text filter documentation.
Dropdown filters are a good choice when users should select from a known set of values without displaying every option permanently in the sidebar.
Unfold provides several dropdown variants.
Use ChoicesDropdownFilter for model fields that define choices.
from unfold.contrib.filters.admin import ChoicesDropdownFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = [
("status", ChoicesDropdownFilter),
]
For example, an order status field could present values such as Pending, Processing, Completed, and Canceled inside a compact dropdown.
Use RelatedDropdownFilter for ForeignKey or other related fields when the number of related objects is reasonably small.
from unfold.contrib.filters.admin import RelatedDropdownFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = [
("country", RelatedDropdownFilter),
]
Dropdowns use Select2 by default, which gives them a consistent and compact interface.
For large related datasets, prefer an autocomplete filter instead of loading every related object into the dropdown.
Read more in the dropdown filter documentation.
Many admin workflows need to filter by several values at the same time.
For example, an order manager might want to see both Pending and Processing orders in one view.
Unfold provides multiple-selection versions of its dropdown filters:
MultipleChoicesDropdownFilterMultipleRelatedDropdownFilterfrom unfold.contrib.filters.admin import MultipleChoicesDropdownFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = [
("status", MultipleChoicesDropdownFilter),
]
Multiple selections are especially useful for:
They make it possible to express common operational queries without creating a custom filter for every combination of values.
Numeric fields often need more flexible filtering than a fixed list of values.
Unfold provides several numeric filter types:
SingleNumericFilterRangeNumericFilterSliderNumericFilterRangeNumericListFilterRangeNumericFilter allows users to enter minimum and maximum values.
from unfold.contrib.filters.admin import RangeNumericFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter_submit = True
list_filter = [
("total", RangeNumericFilter),
]
Typical use cases include:
For values with a known useful range, SliderNumericFilter provides a more visual interaction.
from unfold.contrib.filters.admin import SliderNumericFilter
class PriceSliderFilter(SliderNumericFilter):
STEP = 10
MAX_DECIMALS = 2
@admin.register(Product)
class ProductAdmin(ModelAdmin):
list_filter = [
("price", PriceSliderFilter),
]
RangeNumericListFilter is useful when the value is not a direct model field.
For example, an admin could annotate each customer with the number of orders and then filter customers by that calculated count.
from django.db.models import Count
from unfold.contrib.filters.admin import RangeNumericListFilter
class OrdersCountFilter(RangeNumericListFilter):
title = "Orders"
parameter_name = "orders_count"
@admin.register(Customer)
class CustomerAdmin(ModelAdmin):
list_filter_submit = True
list_filter = [OrdersCountFilter]
def get_queryset(self, request):
return (
super()
.get_queryset(request)
.annotate(
orders_count=Count("orders", distinct=True),
)
)
Read more in the numeric filter documentation.
Date filtering is common in reporting, order management, audit logs, customer administration, and almost every other operational interface.
Unfold provides two range filters:
RangeDateFilterRangeDateTimeFilterfrom unfold.contrib.filters.admin import RangeDateFilter, RangeDateTimeFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter_submit = True
list_filter = [
("created_at", RangeDateTimeFilter),
("delivery_date", RangeDateFilter),
]
Instead of choosing from predefined relative periods, users can select explicit start and end values.
This is useful for questions such as:
Read more in the date and datetime filter documentation.
Normal dropdowns become difficult to use when a related model contains hundreds or thousands of objects.
For these cases, Unfold provides autocomplete filters:
AutocompleteSelectFilterAutocompleteSelectMultipleFilterfrom unfold.contrib.filters.admin import AutocompleteSelectFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = [
("customer", AutocompleteSelectFilter),
]
The related model admin must define search_fields:
@admin.register(Customer)
class CustomerAdmin(ModelAdmin):
search_fields = ["name", "email"]
Autocomplete filters are particularly useful for:
For relationships where several values should be selected at once, use AutocompleteSelectMultipleFilter.
from unfold.contrib.filters.admin import AutocompleteSelectMultipleFilter
@admin.register(Product)
class ProductAdmin(ModelAdmin):
list_filter = [
("categories", AutocompleteSelectMultipleFilter),
]
Read more in the autocomplete filter documentation.
Dropdowns keep the interface compact, but sometimes it is better to show every available option immediately.
Unfold includes both checkbox and radio filter variants.
Use ChoicesRadioFilter when a field has a small set of mutually exclusive choices.
from unfold.contrib.filters.admin import ChoicesRadioFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = [
("status", ChoicesRadioFilter),
]
Use ChoicesCheckboxFilter when users should be able to select several choices at once.
from unfold.contrib.filters.admin import ChoicesCheckboxFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = [
("status", ChoicesCheckboxFilter),
]
BooleanRadioFilter provides a simple radio interface for boolean fields.
from unfold.contrib.filters.admin import BooleanRadioFilter
@admin.register(Product)
class ProductAdmin(ModelAdmin):
list_filter = [
("is_active", BooleanRadioFilter),
]
RelatedCheckboxFilter allows several related objects to be selected directly from a visible checkbox list.
from unfold.contrib.filters.admin import RelatedCheckboxFilter
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = [
("country", RelatedCheckboxFilter),
]
AllValuesCheckboxFilter automatically creates checkbox options from distinct values stored in a field.
from unfold.contrib.filters.admin import AllValuesCheckboxFilter
@admin.register(Product)
class ProductAdmin(ModelAdmin):
list_filter = [
("brand", AllValuesCheckboxFilter),
]
Checkbox and radio filters work best when the number of options is limited. For larger datasets, a dropdown or autocomplete usually produces a cleaner interface.
Read more in the checkbox and radio filter documentation.
Unfold's filter classes are not limited to direct model fields. You can subclass the base filters when the available values or query logic depend on your application.
For example, a custom dropdown can represent a business concept rather than a database field:
from django.core.validators import EMPTY_VALUES
from django.utils.translation import gettext_lazy as _
from unfold.contrib.filters.admin import DropdownFilter
class OrderValueFilter(DropdownFilter):
title = _("Order value")
parameter_name = "value"
def lookups(self, request, model_admin):
return [
("small", _("Under €100")),
("medium", _("€100 - €500")),
("large", _("Over €500")),
]
def queryset(self, request, queryset):
if self.value() in EMPTY_VALUES:
return queryset
if self.value() == "small":
return queryset.filter(total__lt=100)
if self.value() == "medium":
return queryset.filter(total__gte=100, total__lte=500)
if self.value() == "large":
return queryset.filter(total__gt=500)
return queryset
Then add the custom filter directly to list_filter:
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = [OrderValueFilter]
The same pattern can be used with Unfold's TextFilter, RadioFilter, CheckboxFilter, DropdownFilter, and MultipleDropdownFilter base classes.
This is useful when you want custom filtering logic while keeping the same UI as the built-in Unfold filters.
Unfold also allows individual filters to be configured through list_filter_options.
For example, a filter can have a custom label and use a horizontal layout:
from django.utils.translation import gettext_lazy as _
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_filter = ["status"]
list_filter_options = {
"status": {
"label": _("Order status"),
"horizontal": True,
},
}
A horizontal layout works particularly well for filters with a small number of choices because it keeps frequently used options close to the changelist instead of stacking them vertically.
You can also create a custom Django list filter class with horizontal = True when you need the same layout for a reusable filter.
Read more in the horizontal filter documentation.
The biggest benefit of Unfold's filtering system appears when several filter types are combined around a real workflow.
For example, an order administration page might need to filter by order number, status, customer, value, and creation date at the same time:
from django.contrib import admin
from unfold.admin import ModelAdmin
from unfold.contrib.filters.admin import (
AutocompleteSelectFilter,
ChoicesCheckboxFilter,
FieldTextFilter,
RangeDateTimeFilter,
RangeNumericFilter,
)
from .models import Order
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_display = [
"number",
"status",
"customer",
"total",
"created_at",
]
list_filter_submit = True
list_filter = [
("number", FieldTextFilter),
("status", ChoicesCheckboxFilter),
("customer", AutocompleteSelectFilter),
("total", RangeNumericFilter),
("created_at", RangeDateTimeFilter),
]
This creates a much more useful operational interface without replacing the Django admin changelist or building a separate frontend.
The exact filter set should reflect how users work with the data. A small number of relevant filters is usually better than exposing every available field.
A useful starting point is to match the interaction to the type and amount of data being filtered.
| Requirement | Unfold filter |
|---|---|
| Filter one text field | FieldTextFilter |
| Custom text query | TextFilter |
| Field with predefined choices | ChoicesDropdownFilter |
| Select several predefined choices | MultipleChoicesDropdownFilter |
| Small related dataset | RelatedDropdownFilter |
| Select several related objects | MultipleRelatedDropdownFilter |
| Large related dataset | AutocompleteSelectFilter |
| Select several values from a large relation | AutocompleteSelectMultipleFilter |
| Exact or minimum numeric value | SingleNumericFilter |
| Minimum and maximum number | RangeNumericFilter |
| Visual numeric range | SliderNumericFilter |
| Date range | RangeDateFilter |
| Datetime range | RangeDateTimeFilter |
| Small visible single-choice list | ChoicesRadioFilter |
| Small visible multiple-choice list | ChoicesCheckboxFilter |
| Boolean field | BooleanRadioFilter |
| Related objects as visible choices | RelatedCheckboxFilter |
| Distinct database values as checkboxes | AllValuesCheckboxFilter |
The most important distinction is usually the size of the option set. Radio buttons and checkboxes are excellent when there are only a few values. Dropdowns keep larger sets compact. Autocomplete is a better fit once a related table becomes too large to load and scan comfortably.
Having many filter types available does not mean every changelist needs many filters.
A few practical rules help keep the interface useful.
Avoid rendering hundreds or thousands of customers, products, or users inside a regular dropdown. Autocomplete scales better and lets users search directly for the related object they need.
Multiple-choice filters are useful for statuses, teams, categories, and similar fields where combinations are meaningful. If users nearly always choose one value, a radio or single dropdown is simpler.
Prices, dates, quantities, and scores are usually easier to work with as ranges than as long lists of predefined values.
Frequently used filters should be easy to understand and quick to reach. Horizontal layouts, radio inputs, and checkboxes can be helpful for a small set of high-value filters.
Filters eventually become ORM queries. When working with large datasets, pay attention to joins, annotations, related fields, and database indexes used by frequently applied filters.
The default Django admin filtering API provides a solid foundation, but real internal tools often need richer inputs than a list of links.
Unfold keeps the standard ModelAdmin.list_filter workflow while adding reusable controls for common operational requirements: text inputs, dropdowns, multiple selections, numeric ranges, date ranges, autocomplete, checkboxes, radio buttons, and flexible layouts.
This makes it possible to turn a basic changelist into a much more efficient working interface without moving filtering logic into a separate frontend.
Explore the complete Unfold filters documentation for all configuration options, or open the Unfold live demo to see the admin interface in practice.
For a broader overview of the features available in Unfold, read How to customize Django admin with Unfold.
No. Unfold extends the existing Django admin filtering system. Filters continue to be configured through ModelAdmin.list_filter, so regular Django filters and Unfold filters can be used together.
Use AutocompleteSelectFilter when the related model contains many records. It avoids presenting the entire relationship as one large dropdown and allows users to search for the related object instead.
Yes. Unfold includes multiple-selection dropdowns, autocomplete filters, and checkbox filters. Examples include MultipleChoicesDropdownFilter, MultipleRelatedDropdownFilter, AutocompleteSelectMultipleFilter, and ChoicesCheckboxFilter.
Yes. Unfold provides base classes such as TextFilter, DropdownFilter, MultipleDropdownFilter, RadioFilter, and CheckboxFilter. You can subclass them and implement your own lookup options and queryset logic while retaining Unfold's filter interface.
Django admin theme built with Tailwind CSS to bring modern look and feel to your admin interface. Already contains several built-in features for smooth developer experience.
© 2023 - 2026 Created by unfoldadmin.com. All rights reserved.