Skip to content

Filters

Full attribute and method reference for the filter system, generated from docstrings. For a task-oriented walkthrough, see Filters and Custom Filters.

The classes below are backend-agnostic: they declare a filter's name, label, and data_type, but not its query logic. Each ORM backend (contrib.sqla, contrib.beanie, contrib.mongoengine, contrib.tortoise) subclasses them to add the actual apply() implementation for that backend. See the relevant integration page for the concrete, importable filter classes.

Core types

starlette_admin.filters.base.FilterDataType

Bases: StrEnum

The kind of value a BaseFilter operates on. This informs the filter builder UI which input widget to render for the filter's value(s), and indicates when no input is needed for value-less filters.

Attributes:

Name Type Description
STRING

Plain text input.

NUMBER

Numeric input.

DATE

Date picker (<input type="date">) (for DateField).

DATETIME

Date and time picker (<input type="datetime-local">) (for DateTimeField/ArrowField).

TIME

Time picker (<input type="time">) (for TimeField).

BOOLEAN

True/false toggle.

ENUM

Single or multi-select dropdown.

ARRAY

Free-text tag input (Select2 tags) (for list or array fields such as TagsField). The value is parsed as a comma-separated list.

NONE

No input (for filters that do not require a value, e.g., "is null").

Source code in starlette_admin/filters/base.py
class FilterDataType(StrEnum):
    """The kind of value a [BaseFilter][starlette_admin.filters.BaseFilter] operates on. This informs the filter builder UI which input widget to render for the filter's value(s), and indicates when no input is needed for value-less filters.

    Attributes:
        STRING: Plain text input.
        NUMBER: Numeric input.
        DATE: Date picker (`<input type="date">`) (for `DateField`).
        DATETIME: Date and time picker (`<input type="datetime-local">`) (for `DateTimeField`/`ArrowField`).
        TIME: Time picker (`<input type="time">`) (for `TimeField`).
        BOOLEAN: True/false toggle.
        ENUM: Single or multi-select dropdown.
        ARRAY: Free-text tag input (Select2 tags) (for list or array fields such as `TagsField`). The value is parsed as a comma-separated list.
        NONE: No input (for filters that do not require a value, e.g., "is null").
    """

    STRING = "string"
    NUMBER = "number"
    DATE = "date"
    DATETIME = "datetime"
    TIME = "time"
    BOOLEAN = "boolean"
    ENUM = "enum"
    ARRAY = "array"
    NONE = "none"

starlette_admin.filters.base.BaseFilter

Bases: ABC

Base class for all filters.

A filter is responsible for three things:

  1. Declaring what kind of value it needs (data_type, has_value2) so the filter builder UI can render the appropriate input(s).
  2. Parsing the raw (string) value from the URL into the value apply() will receive (parse_value), raising FilterValidationError if it is not acceptable.
  3. Applying itself to a query (apply). Given a FilterApplyContext with all necessary context, it returns the modified query. It never reads global state, which ensures its portability across backends. Each ORM contrib package provides concrete subclasses that implement apply for its own query representation (see get_filter_registry() on the relevant ModelView).

Attributes:

Name Type Description
name str

A slug identifying this filter, e.g., "eq", "contains", "gt". Used in the serialized filter JSON and for registry lookups.

label str

A human-readable label shown in the filter builder dropdown.

data_type FilterDataType

The kind of value this filter operates on. This informs the filter builder UI which input widget to render for the value(s). [FilterDataType.NONE][starlette_admin.types.FilterDataType] means the filter requires no value at all (e.g., "is null" or "is true"), so the UI renders no input, and _parse_list_params does not require a value in the rule.

has_value2 bool

True for filters that require a second value, e.g., "between".

Source code in starlette_admin/filters/base.py
class BaseFilter(ABC):
    """Base class for all filters.

    A filter is responsible for three things:

    1. Declaring what kind of value it needs (`data_type`, `has_value2`) so the filter builder UI can render the appropriate input(s).
    2. Parsing the raw (string) value from the URL into the value `apply()` will receive (`parse_value`), raising [FilterValidationError][starlette_admin.filters.FilterValidationError] if it is not acceptable.
    3. Applying itself to a query (`apply`). Given a [FilterApplyContext][starlette_admin.filters.FilterApplyContext] with all necessary context, it returns the modified query. It never reads global state, which ensures its portability across backends. Each ORM contrib package provides concrete subclasses that implement `apply` for its own query representation (see `get_filter_registry()` on the relevant `ModelView`).

    Attributes:
        name: A slug identifying this filter, e.g., `"eq"`, `"contains"`, `"gt"`. Used in the serialized filter JSON and for registry lookups.
        label: A human-readable label shown in the filter builder dropdown.
        data_type: The kind of value this filter operates on. This informs the filter builder UI which input widget to render for the value(s). [FilterDataType.NONE][starlette_admin.types.FilterDataType] means the filter requires no value at all (e.g., "is null" or "is true"), so the UI renders no input, and `_parse_list_params` does not require a `value` in the rule.
        has_value2: `True` for filters that require a second value, e.g., "between".
    """

    name: ClassVar[str]
    label: ClassVar[str]
    data_type: ClassVar[FilterDataType]
    has_value2: ClassVar[bool] = False

    def parse_value(self, raw: str) -> Any:
        """Parse the raw string value from the URL into the value `apply()` will receive as `ctx.value` (or `ctx.value2`).

        Override this method to convert values into richer types, e.g., `Decimal`, `date`, etc. The default implementation passes the raw string through unchanged.
        """
        return raw

    def get_choices(self, request: Request) -> Sequence[tuple[Any, str]] | None:
        """Optional `(value, label)` pairs for this filter's value picker, independent of the field's own choices ([EnumField][starlette_admin.fields.EnumField] is the only field that supplies choices on its own).

        Override this for a filter whose value should come from a dynamic, per-request list rather than a typed-in string, e.g. an "is one of" filter over a relation field where the value is a foreign key but the picker should show a human-readable label. A non-empty result here makes the filter builder render this filter's value input as a dropdown seeded with these pairs, taking precedence over the field's own choices.

        The default implementation returns `None`, leaving the value input as the plain input the filter's `data_type` implies (or the field's own choices, for a field like `EnumField` that supplies them).
        """
        return None

    @abstractmethod
    def apply(self, ctx: FilterApplyContext) -> Any:
        """Apply this filter to a query.

        This method receives a [FilterApplyContext][starlette_admin.filters.FilterApplyContext] with all necessary information and must return the modified query object. Implementations must not mutate `ctx.query` in place for dict-based backends (e.g., PyMongo); instead, they should return a new or updated copy.
        """
        raise NotImplementedError()

apply(ctx) abstractmethod

Apply this filter to a query.

This method receives a FilterApplyContext with all necessary information and must return the modified query object. Implementations must not mutate ctx.query in place for dict-based backends (e.g., PyMongo); instead, they should return a new or updated copy.

Source code in starlette_admin/filters/base.py
@abstractmethod
def apply(self, ctx: FilterApplyContext) -> Any:
    """Apply this filter to a query.

    This method receives a [FilterApplyContext][starlette_admin.filters.FilterApplyContext] with all necessary information and must return the modified query object. Implementations must not mutate `ctx.query` in place for dict-based backends (e.g., PyMongo); instead, they should return a new or updated copy.
    """
    raise NotImplementedError()

get_choices(request)

Optional (value, label) pairs for this filter's value picker, independent of the field's own choices (EnumField is the only field that supplies choices on its own).

Override this for a filter whose value should come from a dynamic, per-request list rather than a typed-in string, e.g. an "is one of" filter over a relation field where the value is a foreign key but the picker should show a human-readable label. A non-empty result here makes the filter builder render this filter's value input as a dropdown seeded with these pairs, taking precedence over the field's own choices.

The default implementation returns None, leaving the value input as the plain input the filter's data_type implies (or the field's own choices, for a field like EnumField that supplies them).

Source code in starlette_admin/filters/base.py
def get_choices(self, request: Request) -> Sequence[tuple[Any, str]] | None:
    """Optional `(value, label)` pairs for this filter's value picker, independent of the field's own choices ([EnumField][starlette_admin.fields.EnumField] is the only field that supplies choices on its own).

    Override this for a filter whose value should come from a dynamic, per-request list rather than a typed-in string, e.g. an "is one of" filter over a relation field where the value is a foreign key but the picker should show a human-readable label. A non-empty result here makes the filter builder render this filter's value input as a dropdown seeded with these pairs, taking precedence over the field's own choices.

    The default implementation returns `None`, leaving the value input as the plain input the filter's `data_type` implies (or the field's own choices, for a field like `EnumField` that supplies them).
    """
    return None

parse_value(raw)

Parse the raw string value from the URL into the value apply() will receive as ctx.value (or ctx.value2).

Override this method to convert values into richer types, e.g., Decimal, date, etc. The default implementation passes the raw string through unchanged.

Source code in starlette_admin/filters/base.py
def parse_value(self, raw: str) -> Any:
    """Parse the raw string value from the URL into the value `apply()` will receive as `ctx.value` (or `ctx.value2`).

    Override this method to convert values into richer types, e.g., `Decimal`, `date`, etc. The default implementation passes the raw string through unchanged.
    """
    return raw

starlette_admin.filters.base.FilterApplyContext dataclass

All the arguments an [apply][starlette_admin.filters.BaseFilter.apply] implementation will ever need, bundled to ensure that adding new context (e.g., locale, timezone) later is a backwards-compatible change. Existing subclasses that ignore the new attributes will continue to function unchanged.

Attributes:

Name Type Description
query Any

The ORM-specific query or filter object being constructed (e.g., a SQLAlchemy Select, a PyMongo filter dict).

field_name str

The name of the field or column to filter on.

value Any

The parsed (not raw) primary value, as returned by [parse_value][starlette_admin.filters.BaseFilter.parse_value].

value2 Any

The parsed secondary value. This is only meaningful when has_value2 is True (e.g., the upper bound of a "between" filter).

request Request | None

The current request, available for user or locale-aware filters.

view Optional[BaseModelView]

The view performing the query.

Source code in starlette_admin/filters/base.py
@dataclass
class FilterApplyContext:
    """All the arguments an [apply][starlette_admin.filters.BaseFilter.apply] implementation will ever need, bundled to ensure that adding new context (e.g., `locale`, `timezone`) later is a backwards-compatible change. Existing subclasses that ignore the new attributes will continue to function unchanged.

    Attributes:
        query: The ORM-specific query or filter object being constructed (e.g., a SQLAlchemy `Select`, a PyMongo filter `dict`).
        field_name: The name of the field or column to filter on.
        value: The parsed (not raw) primary value, as returned by [parse_value][starlette_admin.filters.BaseFilter.parse_value].
        value2: The parsed secondary value. This is only meaningful when `has_value2` is `True` (e.g., the upper bound of a "between" filter).
        request: The current request, available for user or locale-aware filters.
        view: The view performing the query.
    """

    query: Any
    field_name: str
    value: Any
    value2: Any = None
    request: Request | None = None
    view: Optional["BaseModelView"] = None

starlette_admin.filters.base.FilterValidationError

Bases: StarletteAdminException

Raised by [BaseFilter.parse_value][starlette_admin.filters.BaseFilter.parse_value] when a raw value isn't acceptable for that filter (wrong format, out of range, ...). _parse_list_params catches this and rejects the request with HTTP 400 before any ORM code runs.

Source code in starlette_admin/filters/base.py
class FilterValidationError(StarletteAdminException):
    """Raised by [BaseFilter.parse_value][starlette_admin.filters.BaseFilter.parse_value]
    when a raw value isn't acceptable for that filter (wrong format, out of
    range, ...). `_parse_list_params` catches this and rejects the request with
    `HTTP 400` before any ORM code runs.
    """

    def __init__(self, msg: str) -> None:
        super().__init__(msg)
        self.msg = msg

starlette_admin.filters.base.FilterRule dataclass

A single {field, filter, value} leaf in a filter tree, as deserialized from the filter query parameter JSON (see FilterGroup).

Attributes:

Name Type Description
field str

The name of the field to filter on.

filter str

The slug of the BaseFilter to apply (e.g., "contains", "gte").

value Any

The raw value as received from the client; this is replaced with the parsed value once _parse_list_params validates the rule.

value2 Any

The raw secondary value; only present for filters with has_value2.

Source code in starlette_admin/filters/base.py
@dataclass
class FilterRule:
    """A single `{field, filter, value}` leaf in a filter tree, as deserialized from the `filter` query parameter JSON (see [FilterGroup][starlette_admin.filters.FilterGroup]).

    Attributes:
        field: The name of the field to filter on.
        filter: The slug of the [BaseFilter][starlette_admin.filters.BaseFilter] to apply (e.g., `"contains"`, `"gte"`).
        value: The raw value as received from the client; this is replaced with the parsed value once `_parse_list_params` validates the rule.
        value2: The raw secondary value; only present for filters with `has_value2`.
    """

    field: str
    filter: str
    value: Any = None
    value2: Any = None

starlette_admin.filters.base.FilterGroup dataclass

A node in the filter tree: either a leaf FilterRule or a nested AND/OR group of rules or sub-groups, mirroring the JSON the filter builder serialises into the filter query parameter:

{
  "logic": "and",
  "rules": [
    {"field": "name", "filter": "contains", "value": "john"},
    {
      "logic": "or",
      "rules": [
        {"field": "age", "filter": "gte", "value": "18"},
        {"field": "verified", "filter": "is_true"}
      ]
    }
  ]
}

Attributes:

Name Type Description
logic str

How rules combine: "and" or "or".

rules list[Union[FilterGroup, FilterRule]]

The child rules or groups. Empty groups apply no filtering.

Source code in starlette_admin/filters/base.py
@dataclass
class FilterGroup:
    """A node in the filter tree: either a leaf [FilterRule][starlette_admin.filters.FilterRule] or a nested AND/OR group of rules or sub-groups, mirroring the JSON the filter builder serialises into the `filter` query parameter:

    ```json
    {
      "logic": "and",
      "rules": [
        {"field": "name", "filter": "contains", "value": "john"},
        {
          "logic": "or",
          "rules": [
            {"field": "age", "filter": "gte", "value": "18"},
            {"field": "verified", "filter": "is_true"}
          ]
        }
      ]
    }
    ```

    Attributes:
        logic: How `rules` combine: `"and"` or `"or"`.
        rules: The child rules or groups. Empty groups apply no filtering.
    """

    logic: str = "and"
    rules: list[Union["FilterGroup", FilterRule]] = field(default_factory=list)

    def is_empty(self) -> bool:
        """Returns True if this group (recursively) contributes no filtering."""
        return not self.rules

is_empty()

Returns True if this group (recursively) contributes no filtering.

Source code in starlette_admin/filters/base.py
def is_empty(self) -> bool:
    """Returns True if this group (recursively) contributes no filtering."""
    return not self.rules

starlette_admin.filters.registry.FilterRegistry

Maps BaseField subclasses to the BaseFilter classes available for them.

A subclass declares one @filters(FieldType, ...)-decorated method per field type it supports. filters_for resolves a given field to its filters by walking type(field).__mro__ and returning the first registered match, so a field type that has no entry of its own falls back to whatever its nearest registered ancestor declares.

Each ORM contrib package owns one instance of this registry, populated with its own concrete BaseFilter subclasses, and hands it back from ModelView.get_filter_registry(). To change the filters offered for a field type, subclass the contrib registry and override just that one method rather than rebuilding the registry from scratch.

Source code in starlette_admin/filters/registry.py
class FilterRegistry:
    """Maps `BaseField` subclasses to the `BaseFilter` classes available for
    them.

    A subclass declares one `@filters(FieldType, ...)`-decorated method per
    field type it supports. `filters_for` resolves a given field to its
    filters by walking `type(field).__mro__` and returning the first
    registered match, so a field type that has no entry of its own falls back
    to whatever its nearest registered ancestor declares.

    Each ORM contrib package owns one instance of this registry, populated
    with its own concrete `BaseFilter` subclasses, and hands it back from
    `ModelView.get_filter_registry()`. To change the filters offered for a
    field type, subclass the contrib registry and override just that one
    method rather than rebuilding the registry from scratch.
    """

    def __init__(
        self,
        filters: dict[type["BaseField"], Sequence[type["BaseFilter"]]] | None = None,
    ) -> None:
        # Collect every @filters-decorated method on this instance (including
        # inherited ones) and index it by the field types it was declared for.
        self._registry: dict[
            type[BaseField], Callable[[BaseField], list[type[BaseFilter]]]
        ] = {}
        for _name, method in inspect.getmembers(self, predicate=inspect.ismethod):
            if hasattr(method, "_filters_for"):
                for field_type in method._filters_for:
                    self._registry[field_type] = method

        # Plugin-registered filters (see `register_filters` in a backend's
        # filters module) sit between the class's own @filters methods and
        # the caller-supplied dict, so precedence is user > plugin > core.
        for field_type, filter_classes in self._external_filters().items():
            self.register(field_type, *filter_classes)

        # Imperative registrations passed to __init__ take priority over the
        # methods above, since they run after and register() replaces entries.
        for field_type, filter_classes in (filters or {}).items():
            self.register(field_type, *filter_classes)

    def _external_filters(
        self,
    ) -> dict[type["BaseField"], Sequence[type["BaseFilter"]]]:
        """Override in a backend's registry to merge in filters registered
        by plugins for that backend. Empty by default."""
        return {}

    def register(
        self, field_type: type["BaseField"], *filter_classes: type["BaseFilter"]
    ) -> None:
        """Set `filter_classes` as the filters available for `field_type`.

        This is the imperative counterpart to the declarative `@filters`
        methods, useful for registering filters at runtime rather than on a
        subclass. Calling it again for the same `field_type` replaces the
        previous registration outright; it does not merge with it.
        """
        self._registry[field_type] = lambda field: list(filter_classes)

    def filters_for(self, field: "BaseField") -> list[type["BaseFilter"]]:
        """Return the filter classes available for `field`.

        A field's own `filters` attribute, if set, takes precedence over
        anything registered here. Otherwise this walks `type(field).__mro__`
        from most to least specific and returns the filters registered for
        the first matching type. For example, `EmailField` (a `StringField`
        subclass) inherits `StringField`'s filters unless `EmailField` has its
        own registration. Returns an empty list if no type in the MRO is
        registered.
        """
        if field.filters is not None:
            return list(field.filters)
        for cls in type(field).__mro__:
            if cls in self._registry:
                return list(self._registry[cast(type["BaseField"], cls)](field))
        return []

    def get_filter(self, field: "BaseField", name: str) -> type["BaseFilter"] | None:
        """Return the filter class among `filters_for(field)` whose
        `BaseFilter.name` slug matches `name`, or `None` if none match.

        Two callers rely on this: request parsing uses it to validate a
        filter slug coming from the URL, and each backend uses it to resolve
        an already-parsed [FilterRule][starlette_admin.filters.FilterRule]
        back into the concrete filter class whose `apply()` builds the query
        fragment.
        """
        for cls in self.filters_for(field):
            if cls.name == name:
                return cls
        return None

filters_for(field)

Return the filter classes available for field.

A field's own filters attribute, if set, takes precedence over anything registered here. Otherwise this walks type(field).__mro__ from most to least specific and returns the filters registered for the first matching type. For example, EmailField (a StringField subclass) inherits StringField's filters unless EmailField has its own registration. Returns an empty list if no type in the MRO is registered.

Source code in starlette_admin/filters/registry.py
def filters_for(self, field: "BaseField") -> list[type["BaseFilter"]]:
    """Return the filter classes available for `field`.

    A field's own `filters` attribute, if set, takes precedence over
    anything registered here. Otherwise this walks `type(field).__mro__`
    from most to least specific and returns the filters registered for
    the first matching type. For example, `EmailField` (a `StringField`
    subclass) inherits `StringField`'s filters unless `EmailField` has its
    own registration. Returns an empty list if no type in the MRO is
    registered.
    """
    if field.filters is not None:
        return list(field.filters)
    for cls in type(field).__mro__:
        if cls in self._registry:
            return list(self._registry[cast(type["BaseField"], cls)](field))
    return []

get_filter(field, name)

Return the filter class among filters_for(field) whose BaseFilter.name slug matches name, or None if none match.

Two callers rely on this: request parsing uses it to validate a filter slug coming from the URL, and each backend uses it to resolve an already-parsed FilterRule back into the concrete filter class whose apply() builds the query fragment.

Source code in starlette_admin/filters/registry.py
def get_filter(self, field: "BaseField", name: str) -> type["BaseFilter"] | None:
    """Return the filter class among `filters_for(field)` whose
    `BaseFilter.name` slug matches `name`, or `None` if none match.

    Two callers rely on this: request parsing uses it to validate a
    filter slug coming from the URL, and each backend uses it to resolve
    an already-parsed [FilterRule][starlette_admin.filters.FilterRule]
    back into the concrete filter class whose `apply()` builds the query
    fragment.
    """
    for cls in self.filters_for(field):
        if cls.name == name:
            return cls
    return None

register(field_type, *filter_classes)

Set filter_classes as the filters available for field_type.

This is the imperative counterpart to the declarative @filters methods, useful for registering filters at runtime rather than on a subclass. Calling it again for the same field_type replaces the previous registration outright; it does not merge with it.

Source code in starlette_admin/filters/registry.py
def register(
    self, field_type: type["BaseField"], *filter_classes: type["BaseFilter"]
) -> None:
    """Set `filter_classes` as the filters available for `field_type`.

    This is the imperative counterpart to the declarative `@filters`
    methods, useful for registering filters at runtime rather than on a
    subclass. Calling it again for the same `field_type` replaces the
    previous registration outright; it does not merge with it.
    """
    self._registry[field_type] = lambda field: list(filter_classes)

starlette_admin.filters.registry.filters(*field_types)

Class method decorator that registers the decorated method as the source of filters for one or more BaseField subclasses.

Apply it to a method on a FilterRegistry subclass. FilterRegistry.__init__ scans the instance for methods carrying this marker and indexes each by the field_types passed here, so filters_for can look the method up later by field type.

Source code in starlette_admin/filters/registry.py
def filters(
    *field_types: type["BaseField"],
) -> Callable[
    [Callable[..., Sequence[type["BaseFilter"]]]],
    Callable[..., Sequence[type["BaseFilter"]]],
]:
    """Class method decorator that registers the decorated method as the
    source of filters for one or more `BaseField` subclasses.

    Apply it to a method on a `FilterRegistry` subclass. `FilterRegistry.__init__`
    scans the instance for methods carrying this marker and indexes each by
    the `field_types` passed here, so `filters_for` can look the method up
    later by field type.
    """

    def wrap(
        method: Callable[..., Sequence[type["BaseFilter"]]],
    ) -> Callable[..., Sequence[type["BaseFilter"]]]:
        method._filters_for = frozenset(field_types)  # ty: ignore[unresolved-attribute]
        return method

    return wrap

Generic

starlette_admin.filters.generic.EqualFilter

Bases: BaseFilter

field == value. Generic equality, suitable for strings, enums and any other field whose values can be compared as-is. Numbers and temporal fields get their own equality filters (see numeric/date) since they need type-aware parsing.

Source code in starlette_admin/filters/generic.py
class EqualFilter(BaseFilter):
    """`field == value`. Generic equality, suitable for strings, enums and any
    other field whose values can be compared as-is. Numbers and temporal
    fields get their own equality filters (see `numeric`/`date`) since they
    need type-aware parsing.
    """

    name = "eq"
    label = _("Equal")
    data_type = FilterDataType.STRING

starlette_admin.filters.generic.NotEqualFilter

Bases: BaseFilter

field != value. The negated counterpart of EqualFilter.

Source code in starlette_admin/filters/generic.py
class NotEqualFilter(BaseFilter):
    """`field != value`. The negated counterpart of
    [EqualFilter][starlette_admin.filters.generic.EqualFilter].
    """

    name = "neq"
    label = _("Not equal")
    data_type = FilterDataType.STRING

starlette_admin.filters.generic.IsNullFilter

Bases: BaseFilter

field IS NULL (or empty, for collection-like fields). Needs no value.

Source code in starlette_admin/filters/generic.py
class IsNullFilter(BaseFilter):
    """`field IS NULL` (or empty, for collection-like fields). Needs no value."""

    name = "is_null"
    label = _("Is null")
    data_type = FilterDataType.NONE

starlette_admin.filters.generic.IsNotNullFilter

Bases: BaseFilter

field IS NOT NULL (or non-empty, for collection-like fields). Needs no value.

Source code in starlette_admin/filters/generic.py
class IsNotNullFilter(BaseFilter):
    """`field IS NOT NULL` (or non-empty, for collection-like fields).
    Needs no value.
    """

    name = "is_not_null"
    label = _("Is not null")
    data_type = FilterDataType.NONE

Numeric

starlette_admin.filters.numeric.EqualFilter

Bases: BaseFilter

field == value for numeric fields.

Source code in starlette_admin/filters/numeric.py
class EqualFilter(BaseFilter):
    """`field == value` for numeric fields."""

    name = "eq"
    label = _("Equals")
    data_type = FilterDataType.NUMBER

    def parse_value(self, raw: Any) -> int | float:
        return _parse_number(raw)

starlette_admin.filters.numeric.NotEqualFilter

Bases: BaseFilter

field != value for numeric fields.

Source code in starlette_admin/filters/numeric.py
class NotEqualFilter(BaseFilter):
    """`field != value` for numeric fields."""

    name = "neq"
    label = _("Not equal")
    data_type = FilterDataType.NUMBER

    def parse_value(self, raw: Any) -> int | float:
        return _parse_number(raw)

starlette_admin.filters.numeric.GreaterThanFilter

Bases: BaseFilter

field > value.

Source code in starlette_admin/filters/numeric.py
class GreaterThanFilter(BaseFilter):
    """`field > value`."""

    name = "gt"
    label = _("Greater than")
    data_type = FilterDataType.NUMBER

    def parse_value(self, raw: Any) -> int | float:
        return _parse_number(raw)

starlette_admin.filters.numeric.LessThanFilter

Bases: BaseFilter

field < value.

Source code in starlette_admin/filters/numeric.py
class LessThanFilter(BaseFilter):
    """`field < value`."""

    name = "lt"
    label = _("Less than")
    data_type = FilterDataType.NUMBER

    def parse_value(self, raw: Any) -> int | float:
        return _parse_number(raw)

starlette_admin.filters.numeric.GreaterThanOrEqualFilter

Bases: BaseFilter

field >= value.

Source code in starlette_admin/filters/numeric.py
class GreaterThanOrEqualFilter(BaseFilter):
    """`field >= value`."""

    name = "gte"
    label = _("Greater than or equal")
    data_type = FilterDataType.NUMBER

    def parse_value(self, raw: Any) -> int | float:
        return _parse_number(raw)

starlette_admin.filters.numeric.LessThanOrEqualFilter

Bases: BaseFilter

field <= value.

Source code in starlette_admin/filters/numeric.py
class LessThanOrEqualFilter(BaseFilter):
    """`field <= value`."""

    name = "lte"
    label = _("Less than or equal")
    data_type = FilterDataType.NUMBER

    def parse_value(self, raw: Any) -> int | float:
        return _parse_number(raw)

starlette_admin.filters.numeric.BetweenFilter

Bases: BaseFilter

value <= field <= value2.

Source code in starlette_admin/filters/numeric.py
class BetweenFilter(BaseFilter):
    """`value <= field <= value2`."""

    name = "between"
    label = _("Between")
    data_type = FilterDataType.NUMBER
    has_value2 = True

    def parse_value(self, raw: Any) -> int | float:
        return _parse_number(raw)

String

starlette_admin.filters.string.ContainsFilter

Bases: BaseFilter

field contains value (case-insensitive substring match).

Source code in starlette_admin/filters/string.py
class ContainsFilter(BaseFilter):
    """`field` contains `value` (case-insensitive substring match)."""

    name = "contains"
    label = _("Contains")
    data_type = FilterDataType.STRING

starlette_admin.filters.string.NotContainsFilter

Bases: BaseFilter

The negated counterpart of ContainsFilter.

Source code in starlette_admin/filters/string.py
class NotContainsFilter(BaseFilter):
    """The negated counterpart of
    [ContainsFilter][starlette_admin.filters.string.ContainsFilter].
    """

    name = "not_contains"
    label = _("Does not contain")
    data_type = FilterDataType.STRING

starlette_admin.filters.string.StartsWithFilter

Bases: BaseFilter

field starts with value (case-insensitive).

Source code in starlette_admin/filters/string.py
class StartsWithFilter(BaseFilter):
    """`field` starts with `value` (case-insensitive)."""

    name = "startswith"
    label = _("Starts with")
    data_type = FilterDataType.STRING

starlette_admin.filters.string.EndsWithFilter

Bases: BaseFilter

field ends with value (case-insensitive).

Source code in starlette_admin/filters/string.py
class EndsWithFilter(BaseFilter):
    """`field` ends with `value` (case-insensitive)."""

    name = "endswith"
    label = _("Ends with")
    data_type = FilterDataType.STRING

Boolean

starlette_admin.filters.boolean.IsTrueFilter

Bases: BaseFilter

field IS TRUE. Needs no value: selecting it from the filter builder is the assertion.

Source code in starlette_admin/filters/boolean.py
class IsTrueFilter(BaseFilter):
    """`field IS TRUE`. Needs no value: selecting it from the filter builder
    is the assertion.
    """

    name = "is_true"
    label = _("Is true")
    data_type = FilterDataType.NONE

starlette_admin.filters.boolean.IsFalseFilter

Bases: BaseFilter

field IS FALSE. Needs no value, see IsTrueFilter.

Source code in starlette_admin/filters/boolean.py
class IsFalseFilter(BaseFilter):
    """`field IS FALSE`. Needs no value, see
    [IsTrueFilter][starlette_admin.filters.boolean.IsTrueFilter].
    """

    name = "is_false"
    label = _("Is false")
    data_type = FilterDataType.NONE

Date and time

starlette_admin.filters.date.DateEqualFilter

Bases: BaseFilter

field == value, for DateField.

DateTimeEqualFilter and TimeEqualFilter cover DateTimeField/ArrowField and TimeField respectively; they exhibit the same behavior, but with a different data_type (and thus a different input widget or parsed type).

Source code in starlette_admin/filters/date.py
class DateEqualFilter(BaseFilter):
    """`field == value`, for [DateField][starlette_admin.fields.DateField].

    [DateTimeEqualFilter][starlette_admin.filters.date.DateTimeEqualFilter] and [TimeEqualFilter][starlette_admin.filters.date.TimeEqualFilter] cover `DateTimeField`/`ArrowField` and `TimeField` respectively; they exhibit the same behavior, but with a different `data_type` (and thus a different input widget or parsed type).
    """

    name = "eq"
    label = _("Is on")
    data_type = FilterDataType.DATE

    def parse_value(self, raw: Any) -> date | datetime | time:
        return _parse_temporal(self.data_type, raw)

starlette_admin.filters.date.DateTimeEqualFilter

Bases: DateEqualFilter

Source code in starlette_admin/filters/date.py
class DateTimeEqualFilter(DateEqualFilter):
    label = _("Is at")
    data_type = FilterDataType.DATETIME

starlette_admin.filters.date.TimeEqualFilter

Bases: DateEqualFilter

Source code in starlette_admin/filters/date.py
class TimeEqualFilter(DateEqualFilter):
    label = _("Is at")
    data_type = FilterDataType.TIME

starlette_admin.filters.date.DateBetweenFilter

Bases: BaseFilter

value <= field <= value2, for DateField. See DateEqualFilter for how DateTimeBetweenFilter and TimeBetweenFilter relate to it.

Source code in starlette_admin/filters/date.py
class DateBetweenFilter(BaseFilter):
    """`value <= field <= value2`, for
    [DateField][starlette_admin.fields.DateField]. See
    [DateEqualFilter][starlette_admin.filters.date.DateEqualFilter] for how
    [DateTimeBetweenFilter][starlette_admin.filters.date.DateTimeBetweenFilter]
    and [TimeBetweenFilter][starlette_admin.filters.date.TimeBetweenFilter]
    relate to it.
    """

    name = "between"
    label = _("Between")
    data_type = FilterDataType.DATE
    has_value2 = True

    def parse_value(self, raw: Any) -> date | datetime | time:
        return _parse_temporal(self.data_type, raw)

starlette_admin.filters.date.DateTimeBetweenFilter

Bases: DateBetweenFilter

Source code in starlette_admin/filters/date.py
class DateTimeBetweenFilter(DateBetweenFilter):
    data_type = FilterDataType.DATETIME

starlette_admin.filters.date.TimeBetweenFilter

Bases: DateBetweenFilter

Source code in starlette_admin/filters/date.py
class TimeBetweenFilter(DateBetweenFilter):
    data_type = FilterDataType.TIME

starlette_admin.filters.date.DateInPastFilter

Bases: BaseFilter

field is before now. This filter needs no value; the comparison point is always "now", evaluated by the backend at query time (e.g., SQL NOW()), so this filter applies unchanged to date, datetime, and time fields alike.

Source code in starlette_admin/filters/date.py
class DateInPastFilter(BaseFilter):
    """`field` is before now. This filter needs no value; the comparison point is always "now", evaluated by the backend at query time (e.g., SQL `NOW()`), so this filter applies unchanged to date, datetime, and time fields alike."""

    name = "in_past"
    label = _("Is in the past")
    data_type = FilterDataType.NONE

starlette_admin.filters.date.DateInFutureFilter

Bases: BaseFilter

field is after now. See DateInPastFilter.

Source code in starlette_admin/filters/date.py
class DateInFutureFilter(BaseFilter):
    """`field` is after now. See
    [DateInPastFilter][starlette_admin.filters.date.DateInPastFilter].
    """

    name = "in_future"
    label = _("Is in the future")
    data_type = FilterDataType.NONE

Enum

starlette_admin.filters.enum.InFilter

Bases: BaseFilter

field IN (values). Renders as a multi-select in the filter builder.

Source code in starlette_admin/filters/enum.py
class InFilter(BaseFilter):
    """`field IN (values)`. Renders as a multi-select in the filter builder."""

    name = "in"
    label = _("Is one of")
    data_type = FilterDataType.ENUM

    def parse_value(self, raw: Any) -> list[str]:
        return _parse_choices(raw)

starlette_admin.filters.enum.NotInFilter

Bases: BaseFilter

field NOT IN (values). The negated counterpart of InFilter.

Source code in starlette_admin/filters/enum.py
class NotInFilter(BaseFilter):
    """`field NOT IN (values)`. The negated counterpart of
    [InFilter][starlette_admin.filters.enum.InFilter].
    """

    name = "not_in"
    label = _("Is not one of")
    data_type = FilterDataType.ENUM

    def parse_value(self, raw: Any) -> list[str]:
        return _parse_choices(raw)

Array

starlette_admin.filters.array.InFilter

Bases: BaseFilter

List/array field contains at least one of the given values (tag input).

Source code in starlette_admin/filters/array.py
class InFilter(BaseFilter):
    """List/array field contains at least one of the given values (tag input)."""

    name = "in"
    label = _("Is one of")
    data_type = FilterDataType.ARRAY

    def parse_value(self, raw: Any) -> list[str]:
        return _parse_array(raw)

starlette_admin.filters.array.NotInFilter

Bases: BaseFilter

A list or array field contains none of the given values (tag input).

Source code in starlette_admin/filters/array.py
class NotInFilter(BaseFilter):
    """A list or array field contains none of the given values (tag input)."""

    name = "not_in"
    label = _("Is not one of")
    data_type = FilterDataType.ARRAY

    def parse_value(self, raw: Any) -> list[str]:
        return _parse_array(raw)