Page cover image

🍏Unit 11: Multiple Parameters

Introduction

In FastAPI, you can combine different types of request data (Path, Query, and Body) in the same function to build more versatile and dynamic endpoints. Here's a breakdown of how these components work together:

  1. Path Parameters: These are part of the URL path and are used to capture values that are specific to the request. They are essential for identifying resources. For example, in /items/{item_id}, item_id is a path parameter.

  2. Query Parameters: These are optional key-value pairs at the end of the URL, starting with a ? and separated by &. They are used for filtering, sorting, or specifying certain aspects of the request without changing the resource path. For example, in /items?limit=10, limit is a query parameter.

  3. Request Body: This is the data sent by the client to your API. It's typically used with POST, PUT, and PATCH requests to send the content of the item to be created or updated. The request body is usually in JSON format.

Combine Path, Query and Body Parameters

Let's take a look at the following program:

from fastapi import FastAPI, Path
from typing import Annotated
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None


@app.put("/items/{item_id}")
async def update_item(
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
    q: str = None,
    item: Item = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if item:
        results.update({"item": item})
    return results

To evaluate the program, there are three inputs in the request, i.e., a path parameter, a query parameter, and a request body, as shown in Fig. 1. You should note that the function update_item() requires a PUT method.

Fig. 1. An example of a mix of path, query parameters and a request body in Postman

Multiple Body Parameters

In previous program, the body request accepts an input Item, but you can declare multiple body parameters such as Item, User.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None

class User(BaseModel):
    username: str
    full_name: str = None

@app.put("/items/{item_id}")
async def create_item(item: Item, user: User, item_id: int):
    results = {"item_id": item_id, "item": item, "user": user}
    return item

The program above can be evaluated by using Postman, as shown in Fig. 2.

Fig. 2. An example of a mix of path, query parameters and a request body in Postman

Singular Values in Body

If you declare a function parameter as is, because it is a singular value, FastAPI will assume that it is a query parameter. To instruct FastAPI to treat a function parameter as another body key using Body.

from fastapi import FastAPI, Body
from typing import Annotated
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None

@app.put("/items/{item_id}")
async def update_item(
    item_id: int,
    item: Item,
    importance: Annotated[int, Body()]
):
    results = {"item_id": item_id, "item": item, "importance": importance}
    return results

In the above program, the importance is a body request (in JSON format) instead of a query parameter. Fig. 3 shows the program evaluation in Postman.

Fig. 3. Evaluate the program in Postman

Embed a Single Body Parameter

If you only have a single item body parameter from a Pydantic model Item, as we have done in previous programs, FastAPI will then expect its body directly by default. But if you want it to expect a JSON with a key item and inside of it the model contents, as it does when you declare extra body parameters, you can use the special Body parameter embed:

item: Item = Body(embed=True)

Let's take a look at the following program:

from fastapi import FastAPI, Body, Path
from typing import Annotated
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None


@app.put("/items/{item_id}")
async def update_item(
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000, embed=True)],
    q: str = None,
    item: Annotated[Item, Body(embed=True)] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if item:
        results.update({"item": item})
    return results

You should note that the body request to evaluate the above program in Postman in Fig. 4.

Fig. 4. Evaluate the program in Postman

Summary

FastAPI allows you to combine path parameters, query parameters, and request body data in a single function. This is particularly useful when you need to operate on a specific resource and still require additional data for the operation, which may not be part of the resource's unique identifier or when you need to apply certain filters or modifications specified in the query parameters.

Last updated