Filters
Every field on a list page can have its own set of filter operators, such as contains, between, and is null. Your users combine these operators into a nested AND/OR tree, and you never write a complex database query.
The admin derives the available filters from the field's underlying type. You can narrow, extend, or fully replace that set for any field.
from starlette_admin.contrib.sqla import ModelView
class PostView(ModelView):
fields = ["id", "title", "content", "published", "created_at"]
# Enable filtering and searching for these specific fields
searchable_fields = ["title", "content", "published", "created_at"]
See examples/02-filters for a runnable app that covers default filters, per-field overrides, and a custom BaseFilter subclass.
Every field you list in searchable_fields gets a Filters dropdown in the list toolbar. From there, users combine any number of filters to find the rows they need.
How the filter builder works
Selecting the Filters button opens a dropdown form where users build their queries:
- Add filter: Adds a condition row. The user picks a field, chooses an operator from that field's available filters, and provides a value. The input adapts to the operator: a plain text box for
contains, two boxes forbetween, and no input at all foris null. - Add group: Nests a subform with its own
AND/ORselector. Use it to build conditions likeA AND (B OR C). - Match all/any of the following: Sets whether the current level uses
ANDorORlogic. - Apply filters: Submits the form as a
GETrequest. The admin serializes the whole filter tree into a singlefilterquery parameter, described in The filter URL format. - Active filters: Each active filter appears as a removable pill above the table. Selecting the
×resubmits the list with that rule dropped. A nested group collapses into a single pill that users remove as a whole.
Tip
Because the whole filter state lives in the URL, a filtered list is shareable. Your users can bookmark the page and send the link to a colleague.
Overriding filters for a specific field
When the default filters are too broad, or you need something more specific, pass the filters= argument to a field to replace its default set.
You can narrow the list to the operators that matter, extend it with a custom filter, or add operators to a field that defaults to basic null checks, such as TagsField:
from enum import Enum
from starlette_admin import (
DateTimeField,
DecimalField,
EnumField,
StringField,
TagsField,
)
from starlette_admin.contrib.sqla import ModelView
# Import the concrete filter implementations for your specific backend
from starlette_admin.contrib.sqla.filters import (
BetweenFilter,
DateInPastFilter,
DateTimeBetweenFilter,
GreaterThanFilter,
NumericEqualFilter,
)
class ProductStatus(str, Enum):
ACTIVE = "ACTIVE"
OUT_OF_STOCK = "OUT_OF_STOCK"
DISCONTINUED = "DISCONTINUED"
class ProductView(ModelView):
fields = [
"id",
StringField("name"), # Uses the default filter set, no override needed
EnumField("status", enum=ProductStatus), # Uses the default filter set
DecimalField(
"price",
# Narrowed down to just 3 of the 9 default numeric filters
filters=[GreaterThanFilter, BetweenFilter, NumericEqualFilter],
),
DateTimeField("created_at", filters=[DateTimeBetweenFilter, DateInPastFilter]),
]
Import filters from your backend
The filter classes you pass to filters= must be the concrete implementations for your database backend: starlette_admin.contrib.sqla.filters, .beanie.filters, .mongoengine.filters, or .tortoise.filters. Import from your backend's filters module, not from starlette_admin.filters.
The filter URL format
The filter builder serializes its state into the filter query parameter as a compact string.
The format is field__operator for a filter without values, field__operator=value for a single value, and field__operator=value..value2 for a two-value filter such as between. Rules are joined with AND or OR, and parentheses nest a group:
/admin/product/list?filter=created_at__between=2026-01-01..2026-01-31+AND+(price__gt=12+OR+price__eq=8)
Wrap a value in quotes when it contains a space or a parenthesis: name__eq="quoted value". A list value for a multi-select filter such as is one of is comma-separated and needs no quotes: status__in=ACTIVE,OUT_OF_STOCK.
When the URL contains an invalid filter string, such as an unknown field, an unavailable operator, or an unparseable value, the application returns an HTTP 400 error instead of silently dropping part of the condition.
Important
Only the fields you list in searchable_fields receive filters. If you leave searchable_fields unset, every field receives them.
Built-in filter reference
The following table lists every filter available out of the box, the URL slug you see in a bookmarked link, and the kind of value each one expects. Filters marked "two values" need both a value and a value2 in the URL, for example between=2026-01-01..2026-01-31.
| Filter | Slug | Value type | Two values? |
|---|---|---|---|
| Contains | contains |
text | |
| Does not contain | not_contains |
text | |
| Starts with | startswith |
text | |
| Ends with | endswith |
text | |
| Equal | eq |
text, number, date, datetime, or time | |
| Not equal | neq |
text or number | |
| Is null | is_null |
(none) | |
| Is not null | is_not_null |
(none) | |
| Greater than | gt |
number | |
| Less than | lt |
number | |
| Greater than or equal | gte |
number | |
| Less than or equal | lte |
number | |
| Between | between |
number, date, datetime, or time | ✓ |
| Is in the past | in_past |
(none) | |
| Is in the future | in_future |
(none) | |
| Is true | is_true |
(none) | |
| Is false | is_false |
(none) | |
| Is one of | in |
comma-separated list | |
| Is not one of | not_in |
comma-separated list |
If you need a filter for a data type the built-ins don't cover, such as a JSON field or a geo-point, see Custom Filters to write a BaseFilter subclass and register it globally or per field instance.
What's next
- Custom Filters: Write and register a
BaseFiltersubclass. - Actions: Add bulk and row actions to your list pages.
- Views: Learn more about
searchable_fieldsand the rest of the list-page configuration.