Query Building¶
FastAPI CRUD Kit provides powerful query building capabilities including filtering, sorting, field selection, and relationship loading.
Query Parameters¶
Query parameters are parsed from the request URL and converted into a QueryParams object:
from fastapi_crud_kit.query import parse_query_params
query_params = parse_query_params(request.query_params)
The QueryParams object contains:
- filters: List of filter conditions
- sort: List of sort fields
- include: List of relationships to load
- fields: List of fields to select
- page, per_page: Pagination parameters
- limit, offset: Alternative pagination parameters
Filtering¶
Basic Filtering¶
Filter results using query parameters:
GET /categories?filter[name]=Tech
GET /categories?filter[name][eq]=Tech
GET /categories?filter[description][like]=%web%
Filter Operators¶
Supported operators:
eq- Equal (default)ne- Not equallt- Less thanlte- Less than or equalgt- Greater thangte- Greater than or equallike- LIKE pattern matching (case-sensitive)ilike- ILIKE pattern matching (case-insensitive)in- Value in list
Filter Configuration¶
Configure allowed filters using QueryBuilderConfig:
from fastapi_crud_kit.query import AllowedFilters, QueryBuilderConfig
query_config = QueryBuilderConfig(
allowed_filters=[
# Exact match only
AllowedFilters.exact("name"),
# Partial match (LIKE)
AllowedFilters.partial("description"),
# Multiple operators
AllowedFilters(
field="created_at",
default_operator="gte",
allowed_operators=["gte", "lte", "gt", "lt"],
),
# Custom filter with callback
AllowedFilters.custom(
field="status",
callback=lambda query, value: query.where(
Category.status == value.upper()
),
),
],
ignore_invalid_errors=False, # Raise error on invalid filters
)
Filter Examples¶
Exact Match:
Comparison:
GET /categories?filter[price][gte]=100
GET /categories?filter[price][lte]=500
GET /categories?filter[created_at][gt]=2024-01-01
Pattern Matching:
In List:
Multiple Filters:
Custom Filter Callbacks¶
For complex filtering logic, use custom callbacks:
def filter_by_category(query, value):
# Custom logic: filter by category name or ID
if value.isdigit():
return query.where(Category.id == int(value))
else:
return query.where(Category.name == value)
query_config = QueryBuilderConfig(
allowed_filters=[
AllowedFilters.custom("category", filter_by_category),
],
)
Sorting¶
Basic Sorting¶
Sort results using the sort parameter:
GET /categories?sort=name
GET /categories?sort=-created_at # Descending
GET /categories?sort=name&sort=-created_at # Multiple sorts
Prefix with - for descending order.
Sort Configuration¶
Configure allowed sort fields:
from fastapi_crud_kit.query import AllowedSort, QueryBuilderConfig
query_config = QueryBuilderConfig(
allowed_sorts=[
AllowedSort("name"),
AllowedSort("created_at", direction="desc"),
AllowedSort("price", "name"), # Multiple fields
],
)
Sort Examples¶
Single Field:
Multiple Fields:
Field Selection¶
Select specific fields to return:
Field Configuration¶
Configure allowed fields:
from fastapi_crud_kit.query import AllowedField, QueryBuilderConfig
query_config = QueryBuilderConfig(
allowed_fields=[
AllowedField("id"),
AllowedField("name"),
AllowedField("description"),
AllowedField("created_at"),
],
)
Note: Field selection is useful for reducing response size and improving performance.
Include Relations¶
Eagerly load relationships:
Include Configuration¶
Configure allowed includes:
from fastapi_crud_kit.query import AllowedInclude, QueryBuilderConfig
query_config = QueryBuilderConfig(
allowed_includes=[
AllowedInclude("products"),
AllowedInclude("tags"),
AllowedInclude("author", alias="user"), # Use alias in URL
],
)
Include Examples¶
Single Relation:
Multiple Relations:
Nested Relations:
Pagination¶
Page-based Pagination¶
Response:
{
"items": [...],
"total": 150,
"page": 1,
"per_page": 20,
"total_pages": 8,
"has_next": true,
"has_prev": false
}
Limit/Offset Pagination¶
Complete Example¶
from fastapi_crud_kit.crud.base import CRUDBase
from fastapi_crud_kit.query import (
AllowedFilters,
AllowedSort,
AllowedField,
AllowedInclude,
QueryBuilderConfig,
)
class CategoryCRUD(CRUDBase[Category]):
def __init__(self):
query_config = QueryBuilderConfig(
allowed_filters=[
AllowedFilters.exact("name"),
AllowedFilters.partial("description"),
AllowedFilters(
field="created_at",
default_operator="gte",
allowed_operators=["gte", "lte", "gt", "lt"],
),
],
allowed_sorts=[
AllowedSort("name"),
AllowedSort("created_at", direction="desc"),
],
allowed_fields=[
AllowedField("id"),
AllowedField("name"),
AllowedField("description"),
AllowedField("created_at"),
],
allowed_includes=[
AllowedInclude("products"),
AllowedInclude("tags"),
],
ignore_invalid_errors=False,
)
super().__init__(model=Category, use_async=True, query_config=query_config)
Query Examples¶
Complex Query¶
GET /categories?filter[name]=Tech&filter[price][gte]=100&sort=-created_at&include=products&fields=id,name,price&page=1&per_page=20
This query: - Filters by name="Tech" and price >= 100 - Sorts by created_at descending - Includes products relationship - Selects only id, name, and price fields - Returns page 1 with 20 items per page
Search with Pagination¶
Validation¶
When ignore_invalid_errors=False (default), invalid filters, sorts, fields, or includes will raise exceptions:
FilterValidationError: Invalid filter field or operatorSortValidationError: Invalid sort fieldFieldValidationError: Invalid field selectionIncludeValidationError: Invalid relationship include
Set ignore_invalid_errors=True to silently ignore invalid parameters:
query_config = QueryBuilderConfig(
allowed_filters=[...],
ignore_invalid_errors=True, # Ignore invalid parameters
)
Best Practices¶
- Always configure allowed filters: Prevents SQL injection and improves security
- Use field selection: Reduce response size for better performance
- Configure includes: Control which relationships can be loaded
- Use pagination: Always paginate large result sets
- Validate inputs: Set
ignore_invalid_errors=Falsein production - Use indexes: Ensure filtered and sorted fields are indexed
Next Steps¶
- Learn about Database Setup for session management
- Explore Advanced Features for transactions
- Check the API Reference for complete details
Previous: CRUD Operations | Next: Database Setup →