FastAPI Query Parameters: How to Implement Parameter Filtering with Query and Path

When building APIs with FastAPI, parameter handling is one of the core aspects. Query parameters (after the ? in the URL) and path parameters (within the URL path) are the two most common types. FastAPI provides the Query and Path utilities to help you more elegantly handle parameter validation, filtering, and documentation generation. This article will guide you through implementing parameter filtering using these utilities with simple examples.

I. Query Parameters: Basic Usage

Query parameters are key-value pairs after the ? in the URL, e.g., name and age in http://example.com/greet?name=Alice&age=25. FastAPI automatically parses these parameters and maps them to function arguments.

Example 1: Basic Query Parameters

from fastapi import FastAPI

app = FastAPI()

@app.get("/greet")
async def greet(name: str, age: int):
    return {"message": f"Hello, {name}! You are {age} years old."}
  • Key Points:
  • name: str and age: int are function parameters. FastAPI automatically converts query parameters from the URL to the specified types (e.g., string to integer).
  • If name or age is omitted, an error occurs (parameters are required by default).
  • Testing:
    Visit http://localhost:8000/greet?name=Bob&age=20 to get {"message": "Hello, Bob! You are 20 years old."}.

II. Filtering Query Parameters with Query

The Query utility is used to validate, set default values, or describe query parameters. It is useful for limiting parameter length, ensuring numeric ranges, and setting defaults.

1. Making Parameters Optional (Setting Default Values)

If a query parameter is not required, set a default value using Query(None) or directly assign a default.

Example 2: Optional Query Parameters

from fastapi import Query

@app.get("/greet")
async def greet(
    name: str = Query(None, description="Your name (optional)"),  # Default: None
    age: int = Query(18, description="Your age (default: 18)")   # Default: 18
):
    return {"message": f"Hello, {name or 'Guest'}! You are {age} years old."}
  • Key Points:
  • Query(None) marks the parameter as optional (omitting it is allowed).
  • age: int = Query(18) sets a default value; if the user omits age, 18 is used.
  • Testing:
  • Visit http://localhost:8000/greet (no parameters) → Hello, Guest! You are 18 years old..
  • Visit http://localhost:8000/greet?name=CharlieHello, Charlie! You are 18 years old..

2. Parameter Validation: Range and Format

Query supports validation rules like min_length, max_length, ge (greater than or equal), and le (less than or equal).

Example 3: Validating Query Parameters

from fastapi import Query

@app.get("/search")
async def search(
    keyword: str = Query(
        ...,  # Explicitly required (no default)
        min_length=3, 
        max_length=50, 
        description="Search keyword (3-50 characters)"
    ),
    page: int = Query(
        1, 
        ge=1,  # ≥ 1
        le=100,  # ≤ 100
        description="Page number (1-100)"
    )
):
    return {"keyword": keyword, "page": page}
  • Key Points:
  • ... explicitly marks the parameter as required (even without a default).
  • min_length/max_length restrict string length; ge/le restrict numeric ranges.
  • Testing:
  • Valid: http://localhost:8000/search?keyword=abc&page=5 → Returns valid data.
  • Invalid: http://localhost:8000/search?keyword=ab&page=0 → FastAPI returns a 422 error: Validation failed.

III. Path Parameters: Basic Usage

Path parameters are fixed-position parameters in the URL path, e.g., user_id in http://example.com/users/123.

Example 4: Basic Path Parameters

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    return {"user_id": user_id, "message": f"User {user_id} information"}
  • Key Points:
  • user_id: int specifies the parameter type (integer).
  • Accessing http://localhost:8000/users/abc (non-integer) triggers a Type error.

IV. Filtering Path Parameters with Path

Similar to Query, Path validates path parameters, sets defaults, and describes them.

Example 5: Validating Path Parameters

from fastapi import Path

@app.get("/users/{user_id}")
async def get_user(
    user_id: int = Path(
        ...,  # Required by default
        gt=0,  # > 0 (positive integer)
        description="User ID (must be a positive integer)"
    ),
    name: str = Path(
        None,  # Optional
        description="Username (optional)"
    )
):
    return {"user_id": user_id, "name": name or "Not provided"}
  • Key Points:
  • gt=0 ensures user_id is a positive integer (negative/zero values fail validation).
  • Path(None) makes name an optional path parameter.
  • Testing:
  • Valid: http://localhost:8000/users/100{"user_id": 100, "name": "Not provided"}.
  • Invalid: http://localhost:8000/users/-5 → FastAPI returns a 422 error: User ID must be a positive integer.

V. Core Roles of Query and Path

  1. Parameter Validation: Automatically check types, ranges, and formats to prevent invalid data from reaching business logic.
  2. Default Values: Make parameters optional (e.g., Query(None)), improving interface flexibility.
  3. Documentation: FastAPI automatically renders parameter rules (e.g., length, range) in Swagger UI (access /docs to view).

Summary

  • Use Query for query parameters to handle defaults, validation, and descriptions.
  • Use Path for path parameters to restrict integer ranges and enforce types.
  • Query and Path simplify parameter filtering, reduce boilerplate code, and ensure self-documenting APIs via FastAPI’s automatic Swagger UI generation.

By leveraging these utilities, you can build robust, maintainable FastAPI interfaces with efficient parameter handling.

Xiaoye