Field Configuration (json_schema_extra)
Each field in your Pydantic schema can carry metadata that controls how filters are generated for it. This is done through Pydantic's json_schema_extra parameter in Field.
from pydantic import BaseModel, Field
class PostOut(BaseModel):
title: str = Field(
json_schema_extra={
"filters": ["eq", "icontains"],
}
)
Supported Keys
| Key | Type | Required | Description |
|---|---|---|---|
filters |
list[str] |
Yes (to enable filters) | List of operators allowed for this field |
filter_alias |
str |
No | Custom name for the filter parameter in the query string |
filters
Defines which operators are available for this field. If omitted or empty, no filter parameters are generated for the field.
class PostOut(BaseModel):
title: str = Field(json_schema_extra={"filters": ["eq", "icontains"]})
score: float = Field(json_schema_extra={"filters": ["gte", "lte"]})
deleted_at: datetime | None = Field(None, json_schema_extra={"filters": ["isnull"]})
description: str | None = Field(None) # no filters — never filterable
See the full list of supported operators in Operators Reference.
Tip
Only declare the operators your API actually needs. Fewer operators = cleaner Swagger docs and a smaller attack surface.
filter_alias
By default, the filter parameter name is derived from the field name or its Pydantic alias. Use filter_alias to override this with an explicit name for your API.
class PostOut(BaseModel):
title: str = Field(
alias="post_title", # Pydantic response alias
json_schema_extra={
"filters": ["eq", "icontains"],
"filter_alias": "web_title", # filter parameter uses this name
},
)
| Config | Generated Parameter |
|---|---|
With filter_alias |
web_title__eq |
Without filter_alias (uses alias) |
post_title__eq |
Without alias (uses field name) |
title__eq |
Alias Priority
The library follows a specific priority when determining the name of the filter parameter:
filter_aliasinjson_schema_extra(Highest priority)- Pydantic's standard
alias - The Python field name (Lowest priority)
Tip
If you want your filters to match your Pydantic aliases exactly, you don't need to specify filter_alias — it happens automatically.
Combining All Keys
Here is a real-world example:
class PostOut(BaseModel):
id: int = Field(
json_schema_extra={"filters": ["eq", "in", "not_in"]}
)
title: str = Field(
alias="post_title",
json_schema_extra={
"filters": ["eq", "icontains"],
"filter_alias": "post_title",
},
)
user_id: int = Field(
json_schema_extra={
"filters": ["eq"],
"filter_alias": "userId",
},
)
deleted_at: datetime | None = Field(
None,
json_schema_extra={"filters": ["isnull"]},
)
description: str | None = Field(None) # intentionally not filterable
model_config = ConfigDict(from_attributes=True, validate_by_name=True)
Generated filter parameters (with prefix = "f_"):
f_id__eq,f_id__in,f_id__not_inf_post_title__eq,f_post_title__icontainsf_userId__eqf_deleted_at__isnull