Django admin filters with Unfold

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.

  • calendar_month 13.10.2026
  • pace 9 minutes

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.

Enable Unfold filters

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

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:

  • order numbers
  • SKUs
  • email addresses
  • invoice references
  • customer names
  • external IDs

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

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.

Choices dropdown

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.

Related 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.

Multiple-selection dropdown filters

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:

  • MultipleChoicesDropdownFilter
  • MultipleRelatedDropdownFilter
from unfold.contrib.filters.admin import MultipleChoicesDropdownFilter


@admin.register(Order)
class OrderAdmin(ModelAdmin):
    list_filter = [
        ("status", MultipleChoicesDropdownFilter),
    ]

Multiple selections are especially useful for:

  • statuses
  • categories
  • teams
  • locations
  • tags
  • assigned users

They make it possible to express common operational queries without creating a custom filter for every combination of values.

Numeric filters

Numeric fields often need more flexible filtering than a fixed list of values.

Unfold provides several numeric filter types:

  • SingleNumericFilter
  • RangeNumericFilter
  • SliderNumericFilter
  • RangeNumericListFilter

Numeric range filter

RangeNumericFilter 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:

  • order totals
  • product prices
  • inventory levels
  • scores
  • durations
  • quantities
  • account balances

Numeric slider

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),
    ]

Filter annotated values

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 and datetime range filters

Date filtering is common in reporting, order management, audit logs, customer administration, and almost every other operational interface.

Unfold provides two range filters:

  • RangeDateFilter
  • RangeDateTimeFilter
from 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:

  • Which orders were created last week?
  • Which invoices were paid during a reporting period?
  • Which users registered between two dates?
  • Which events are scheduled this month?

Read more in the date and datetime filter documentation.

Autocomplete filters

Normal dropdowns become difficult to use when a related model contains hundreds or thousands of objects.

For these cases, Unfold provides autocomplete filters:

  • AutocompleteSelectFilter
  • AutocompleteSelectMultipleFilter
from 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:

  • customers
  • users
  • companies
  • products
  • suppliers
  • locations

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.

Checkbox and radio filters

Dropdowns keep the interface compact, but sometimes it is better to show every available option immediately.

Unfold includes both checkbox and radio filter variants.

Choices radio filter

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),
    ]

Choices checkbox filter

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),
    ]

Boolean radio filter

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),
    ]

Related checkbox filter

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),
    ]

All values checkbox filter

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.

Build custom dropdown, checkbox, radio, and text filters

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.

Customize filter labels and layout

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.

Combine multiple Unfold filters

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.

Choosing the right Unfold filter

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.

Keep advanced admin filters usable

Having many filter types available does not mean every changelist needs many filters.

A few practical rules help keep the interface useful.

Use autocomplete for large relationships

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.

Use multiple selection only when users need combinations

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.

Prefer ranges for continuous values

Prices, dates, quantities, and scores are usually easier to work with as ranges than as long lists of predefined values.

Keep important filters visible

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.

Measure expensive queries

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.

Build more useful Django admin changelists with Unfold

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.

Django admin filters with Unfold FAQ

Does Unfold replace Django's list_filter?

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.

Which Unfold filter should I use for a large ForeignKey?

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.

Can Unfold filters select multiple values?

Yes. Unfold includes multiple-selection dropdowns, autocomplete filters, and checkbox filters. Examples include MultipleChoicesDropdownFilter, MultipleRelatedDropdownFilter, AutocompleteSelectMultipleFilter, and ChoicesCheckboxFilter.

Can I create my own Unfold filter?

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.