FastAPI Study Diary (3) — Receiving Request Data

contente

Now that we have our FastAPI development environment set up, I’ve decided to learn about handling requests in FastAPI.

Accepting Path Parameters

It’s similar to Node, so I was able to grasp the concept smoothly. One point to note is that Python also has type specifications. In the example above, the function is written to accept the `book_id` as an int type. This was a fresh perspective for me, as my brain hasn’t been updated for years and still imagines Python as a type-less language. (I later found out that this request handling mechanism uses something called Pydantic for type specifications.)

I decided to run the API I just created.

When I accessed the path `/books/15` on my local host’s 8000 port in the browser, I confirmed from the response JSON that the part ‘15’ was inputted as int type data into `book_id`.

The number 15 from the path parameter is input as book_id.

Next, I tried accessing the path /great_gatsby instead of /15 as below.

A response like the one below is returned.

It seems there was an error because the data “great_gatsby” couldn’t be converted to an integer.

You can see from the FastAPI logs during execution that there was an error like the one below.

Retrieving Nested Path Parameters

Following up from before, I tried receiving multiple path parameters in a request, as shown below.

When you access http://127.0.0.1:8000/books/english/3, you will receive the following response:
{“book_type”: “english”, “book_id”: 3}

This is similar to how Node.js works, so it’s easy to understand.

Validation

I was amazed at how easily FastAPI allows us to add validation for request data.

For instance, in the previous example where we specified the type as int, if we add = Path(..., ge=1000), it will return an error 422 when the value of book_id is less than 1000, as shown below.

If a number less than 100 is entered in the path, an error occurs.

The “…” in Path(…, ge=100)) is typically where you would specify a default value, but since there is no default value in this case, “…” is used instead.

The “ge” in ge=100 is an abbreviation for “greater than or equal to,” meaning that in this case it represents “100 or more.” In other words, Path(…, ge=100)) adds a constraint that the book_id must be 100 or greater.

There are also other options available, such as:
- gt: “greater than”
- lt: “less than”
- le: “less than or equal to”
These allow you to specify the respective conditions.

Validation of Strings

If you specify a single-character string for book_name as shown above, it will result in a 422 error.

In this way, you can add a minimum or maximum number of characters.

Query Parameters

Instead of path parameters, query parameters are not defined in the path definition (@app.get()), but are only included in the function parameters.

I thought it was very simple and easy to understand.

When you send a request without setting query parameters,
http://127.0.0.1:8000/search_book/great

As you see in the browser screenshot, the default values (0 and 10) set in the function parameters are automatically assigned to the offset and limit variables.

When you set the query parameters like in the URL below,
http://127.0.0.1:8000/search_book/great?offset=100&limit=50

The values specified in the query parameters will be assigned accordingly.

To add validation to query parameters, you can use the Query class, as shown below.

The first value passed to the constructor of the Query class is the default value, and the second one is for validation conditions.

If you send a request like http://127.0.0.1:8000/search_book/great?offset=100&limit=500, a 422 error will be returned, as shown below.

Post Request

You can receive information in the body of a POST request with the Body class, as shown below.

One important note is that you need to change from `@app.get()` to `@app.post()`.

While Postman is a good tool to test this POST API, this time I decided to try a tool called HTTPie.

HTTPie

I installed HTTPie using brew.

With HTTPie, posting JSON is very easy. If you type key=value pairs after the endpoint, these key-value pairs are included as JSON data in the post request.

Since the API returns the posted data as it is, we can confirm that the request was properly received.

By the way, if you add the -v option, the contents of the request will also appear in the log, which can be used to check the contents of the header and the request body during debugging.

Pydantic Model

When the data to be posted becomes larger, it becomes cumbersome to define all the data as parameters, as in the previous example, and the visibility also deteriorates.

Using Pydantic models is very convenient because it allows you to generate objects from the content of the request.

The example above is an API that receives the same JSON as the previous example, but this time it receives data from the request as an object of the Photo class. The received Photo class object (photo) is returned as is to the client, but it is automatically converted to JSON, which surprised me because it is too convenient.

To receive a request as an object like this, the Photo class must be a class that inherits from Pydantic’s BaseModel. This is a very important point.

By defining your desired class as a subclass of BaseModel, Pydantic will handle data conversion, validation, and variable assignment for you.

This was my first time learning about Pydantic, and it seems that using it will allow for more extensive validation of request data (for example, checking whether the necessary data for a Photo object is included in the request), making it a central presence in implementing FastAPI.

Stay tuned as I delve deeper into Pydantic and share more insights in upcoming articles.

If you have any questions about this article, feel free to drop me an email at [email protected].

By the way, I work at Goldrush Computing, a mobile app and web development company based in Tokyo and Ho Chi Minh City, Vietnam. If you’re on the lookout for an external team to bring your product to life, don’t hesitate to get in touch!

Next story is:

Resumir
The article discusses handling requests in FastAPI, covering topics such as accepting path parameters, retrieving nested path parameters, validation for request data, validation of strings, query parameters, handling post requests, using HTTPie for testing, Pydantic models for data conversion and validation. It explains how to set up type specifications for path parameters, add validation for request data, and handle query parameters. The article also introduces Pydantic models for handling larger data requests efficiently. The author shares insights on using Pydantic for extensive validation of request data and hints at exploring more about Pydantic in future articles. Overall, the article provides a detailed guide on request handling in FastAPI and highlights the importance of Pydantic for data conversion and validation in API development.