agentbench / data /tech_docs /fastapi_query_params.md
Nomearod's picture
feat: Day 4 — corpus, ingest script, first 10 golden questions
a152b95

Query Parameters in FastAPI

Query parameters are the key-value pairs that appear after the ? in a URL (e.g., /items?skip=0&limit=10). In FastAPI, any function parameter that is not part of the path is automatically interpreted as a query parameter.

Basic Query Parameters

from fastapi import FastAPI

app = FastAPI()

# Sample data
fake_items_db = [{"item_name": f"Item {i}"} for i in range(100)]

@app.get("/items/")
async def read_items(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]

In this example, both skip and limit are query parameters with default values. A request to /items/ uses the defaults (skip=0, limit=10), while /items/?skip=20&limit=5 overrides both. FastAPI automatically converts the string values from the URL into their declared Python types.

Required vs Optional Query Parameters

The distinction between required and optional query parameters depends on whether a default value is provided:

from fastapi import FastAPI, Query
from typing import Optional

app = FastAPI()

@app.get("/search/")
async def search(
    q: str,                          # Required - no default
    category: str = "all",           # Optional - has default
    max_price: Optional[float] = None,  # Optional - default is None
):
    results = {"q": q, "category": category}
    if max_price is not None:
        results["max_price"] = max_price
    return results

If a client calls /search/ without the q parameter, FastAPI returns a 422 Unprocessable Entity error. The category parameter defaults to "all", and max_price defaults to None.

Query Parameter Validation with Query()

The Query() function provides additional validation and metadata:

from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(
    q: str = Query(
        default=None,
        min_length=3,
        max_length=50,
        pattern="^[a-zA-Z0-9 ]+$",
        title="Search query",
        description="The search string to filter items by name",
        example="laptop",
    )
):
    results = {"items": []}
    if q:
        results["q"] = q
    return results

The Query() function supports the following validation parameters for strings:

  • min_length -- minimum character length (default: None, no minimum)
  • max_length -- maximum character length (default: None, no maximum)
  • pattern -- a regular expression the value must match

For numeric query parameters, Query() supports the same gt, ge, lt, and le constraints as Path().

Multiple Values for a Single Query Parameter

To accept a list of values for one query parameter (e.g., /items/?tag=food&tag=drink), declare the parameter as a list:

from typing import List
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(
    tags: List[str] = Query(default=[], description="Filter by tags")
):
    return {"tags": tags}

A request to /items/?tags=food&tags=drink yields tags=["food", "drink"]. The default is an empty list if no tags are provided.

Combining Path and Query Parameters

Path and query parameters work together seamlessly. FastAPI distinguishes them based on whether the parameter name appears in the path template:

@app.get("/users/{user_id}/items/")
async def read_user_items(
    user_id: int,              # Path parameter (in URL path)
    skip: int = 0,             # Query parameter (not in path)
    limit: int = 10,           # Query parameter (not in path)
    include_archived: bool = False,  # Query parameter
):
    return {
        "user_id": user_id,
        "skip": skip,
        "limit": limit,
        "include_archived": include_archived,
    }

A request to /users/42/items/?skip=5&limit=20&include_archived=true passes user_id=42 from the path and all other values from the query string. Boolean query parameters accept true, false, 1, 0, yes, no, on, and off (case-insensitive). FastAPI converts all these values to Python bool.

Deprecating Query Parameters

You can mark a query parameter as deprecated to signal to API consumers that it will be removed in a future version:

@app.get("/items/")
async def read_items(
    q: str = Query(default=None, deprecated=True)
):
    return {"q": q}

The parameter still functions normally, but it appears as deprecated in the generated OpenAPI documentation and Swagger UI.