Filters API Reference
Overview
Filtering is enabled via Meta.filtering on a RestEndpoint:
from lightapi import RestEndpoint, Filtering, FieldFilter, SearchFilter, OrderingFilter
class ArticleEndpoint(RestEndpoint):
title: str
published: bool
class Meta:
filtering = Filtering(
backends=[FieldFilter, SearchFilter, OrderingFilter],
fields=["published"],
search=["title"],
ordering=["title", "created_at"],
)
Filtering
Filtering(
backends: list[type] | None = None,
fields: list[str] | None = None,
search: list[str] | None = None,
ordering: list[str] | None = None,
)
| Parameter | Description |
|---|---|
backends |
Filter backend classes applied in order to every list query. |
fields |
Column names allowed for FieldFilter exact-match. |
search |
Column names searched by SearchFilter. |
ordering |
Column names allowed for OrderingFilter. |
Built-in backends
FieldFilter
Applies exact WHERE col = value for query parameters in fields.
Type coercion: string query parameter values are automatically converted to the correct Python type (bool, int, float) based on the SQLAlchemy column type. A value an int or float column cannot parse (?pages=lots) answers 422 with {"detail": [{"loc": ["query", "pages"], ...}]} instead of reaching the database.
Class: lightapi.filters.FieldFilter
SearchFilter
Applies case-insensitive ILIKE '%value%' across all search columns when ?search= is present.
GET /articles?search=async+python
# WHERE title ILIKE '%async python%' OR body ILIKE '%async python%'
Search input is treated as a literal string. The characters % and _ (SQL LIKE wildcards) are automatically escaped, so ?search=hello_world matches only the exact substring hello_world — not any single character in place of the underscore. Bare % or _ characters in search terms do not become wildcards.
Class: lightapi.filters.SearchFilter
OrderingFilter
Applies ORDER BY col ASC or ORDER BY col DESC (prefix -) via ?ordering=.
Multiple fields can be comma-separated. Only fields explicitly listed in ordering are allowed; unknown field names are silently ignored. When ordering is not configured (empty or omitted), the backend ignores all ?ordering= parameters — no ordering is applied. This prevents clients from sorting by arbitrary columns when no whitelist has been declared.
Class: lightapi.filters.OrderingFilter
Reserved parameters
The following query parameter names are never treated as field filters:
page, page_size, cursor, search, ordering
BaseFilter
Implement this abstract base class to create custom filter backends:
from lightapi.filters import BaseFilter
from starlette.requests import Request
class DateRangeFilter(BaseFilter):
def filter_queryset(self, request: Request, queryset, view) -> Any:
after = request.query_params.get("after")
before = request.query_params.get("before")
cls = type(view)
if after:
queryset = queryset.where(cls._model_class.created_at >= after)
if before:
queryset = queryset.where(cls._model_class.created_at <= before)
return queryset
Register it in Meta.filtering:
class EventEndpoint(RestEndpoint):
name: str
class Meta:
filtering = Filtering(
backends=[FieldFilter, DateRangeFilter, OrderingFilter],
fields=[],
ordering=["created_at"],
)
_coerce_filter_value (internal)
LightAPI calls this automatically for FieldFilter to coerce string query params to the column's Python type. You can use it in custom backends: