Query Parameters
Query parameters are the key-value pairs that appear after the ? in a URL, typically used for filtering, sorting, and pagination. In this codebase, query parameters are managed through the Query class and its base class Param, both located in fastapi/params.py.
Core Parameter Classes
The implementation of query parameters relies on a hierarchy that integrates with Pydantic's validation system:
Param: The base class for all request parameters (Query, Path, Header, Cookie). It inherits from Pydantic'sFieldInfoand adds anin_attribute to specify the parameter's location in the request.Query: A specialized version ofParamwherein_is set toParamTypes.query. It provides the interface for defining metadata and validation rules specific to URL query strings.
# fastapi/params.py
class Param(FieldInfo):
in_: ParamTypes
# ... handles common logic for aliases, validation, and metadata
class Query(Param):
in_ = ParamTypes.query
# ... inherits all validation and metadata capabilities
Defining Query Parameters
FastAPI automatically interprets function parameters that are not part of the path as query parameters. You can define them using simple type hints or by using the Query class for more control.
Implicit Query Parameters
If you provide a type hint but no default value or Query instance, the parameter is treated as a required query parameter. If you provide a default value, it becomes optional.
@app.get("/items/")
async def read_items(q: str | None = None, skip: int = 0, limit: int = 10):
return {"q": q, "skip": skip, "limit": limit}
Explicit Definition with Query
The Query class allows you to add validation and metadata. The modern and recommended approach in this codebase is to use Annotated.
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(max_length=50, min_length=3)] = None
):
return {"q": q}
Validation and Constraints
The Query class supports a wide range of validation constraints inherited from Param and Pydantic's FieldInfo.
String Validations
You can constrain strings using length limits and regular expression patterns (using the pattern parameter).
@app.get("/items/")
async def read_items(
q: Annotated[
str | None,
Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None
):
return {"q": q}
Note: The regex parameter is deprecated in favor of pattern in fastapi/params.py.
Numeric Validations
For integer or float parameters, you can use:
gt: Greater thange: Greater than or equallt: Less thanle: Less than or equal
@app.get("/items/")
async def read_items(
limit: Annotated[int, Query(gt=0, le=100)] = 10
):
return {"limit": limit}
Required vs. Optional Parameters
A query parameter's requirement is determined by its default value:
- Optional: Provide a default value (e.g.,
Noneor10). - Required: Do not provide a default value, or explicitly use
...(Ellipsis) orUndefined.
from fastapi import Query
from fastapi._compat import Undefined
@app.get("/items/")
async def read_items(
q: str = Query(default=...), # Required
p: str = Query(default=Undefined) # Also Required
):
return {"q": q, "p": p}
Advanced Configuration
Aliases
Query parameters often need to use characters that are not valid Python variable names, such as hyphens. The alias parameter allows you to map a URL parameter name to a different function argument name.
@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(alias="item-query")] = None
):
# Client sends ?item-query=foo, but code uses 'q'
return {"q": q}
Multiple Values (Lists)
To accept multiple values for the same query parameter (e.g., ?q=foo&q=bar), define the type hint as a list.
@app.get("/items/")
async def read_items(q: Annotated[list[str] | None, Query()] = None):
return {"q": q}
Grouping with Pydantic Models
For complex sets of query parameters, you can group them into a Pydantic model. This promotes reusability and cleaner function signatures.
from pydantic import BaseModel, Field
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
@app.get("/items/")
async def read_items(filter_query: FilterParams = Query()):
return filter_query
OpenAPI Metadata
The Query class includes several parameters that do not affect validation but are used to generate the OpenAPI schema and documentation:
title: A human-readable name for the parameter.description: A detailed explanation of what the parameter does.examples: A list of example values to show in the documentation.deprecated: Marks the parameter as deprecated in the schema.include_in_schema: Set toFalseto hide the parameter from the generated OpenAPI documentation.
@app.get("/items/")
async def read_items(
q: Annotated[
str | None,
Query(
title="Query string",
description="Query string for the items to search in the database",
examples=["foo", "bar"],
deprecated=True
),
] = None
):
return {"q": q}