Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

FastAPI GET Requests

00:00 Right now the API can only return the data it wants to. You have no say in what data is returned. For example, consider the following list of items represented as dictionaries in Python.

00:14 Now add the following code to your API.

00:29 You can either retrieve all the shapes using the /shapes endpoint, or none of them by not invoking the /shapes endpoint. What if you want to get a specific shape by its ID?

00:41 You would need a way to provide input to the API. With a REST API, you generally provide input values in the path of the endpoint. For example, the path /shapes/3 would retrieve the shape with an ID equal to 3.

00:58 What you want is for the path segment after shapes to be a variable, and FastAPI uses path parameters to do this. To specify a path segment as a parameter, give it a name, surrounded by a pair of curly braces ({}). Then use that path in the @get decorator.

01:20 Now, if a GET request is made to the endpoint /shapes/3, the value 3 will be put in the variable name, shape_id, and provided to the get_shape_by_id() function.

01:45 To see it in action, go to localhost:8000/docs in the browser. Expand the Get Shape By Id endpoint. Click the Try it out button.

01:58 In the shape_id text input, enter 2. Click Execute and look at the result. null?

02:11 The list of shapes has a shape with ID 2. It’s a triangle. So why is the API returning null? To understand this, first we need to talk a little about Python type hints.

02:25 As you may be aware, Python is a dynamically typed language, and thus a variable assumes the type of its value. This is a feature called type inference and is part of many different languages, not just those which are dynamically typed. Python takes this a step further and allows the type of a variable to change with its value.

02:45 This is one reason that there are no type specifiers required in Python. You don’t declare the variable meaning_of_life to be an integer. You assign it an integer value, and thus the variable is assumed to be of type int.

02:59 If you change the value to a string, such as the words "forty-two, the type of the variable will become a str. In Python 3.5, the idea of type hints were introduced. In other words, you can now optionally specify data types for variables, parameters, and return values. For example, the get_shape_by_id() function expects the shape_id to be an int because the ID key of the dictionaries for the shapes is an int.

03:29 To specify this with a type hint, place a colon (:) after the shape_id and then the type of int.

03:40 The strange thing about this code is that Python by default will not enforce the type hint. You would still be able to call get_shape_by_id() and give it a string, an int, or a float.

03:52 You have to run the code through a preprocessor such as mypy. If mypy sees the code trying to call get_shape_by_id() with a string, it will tell you, but not prevent Python from trying to run the app.

04:05 However, there is a Python package called pydantic, which will enforce type hints at runtime, and FastAPI makes extensive use of the pydantic package to enforce type hints. Thus, the get_shape_by_id() function will only accept integers.

04:23 Take a look at the Swagger docs after the application restarts. Notice underneath the parameter name, shape_id is a type integer. Click the Try it out button again and enter 2 for the value. Click Execute, and you’ll see that the JSON for the triangle is returned.

04:45 So why did it not work without the type hint? That’s because by default, all path parameters are assumed to be strings. Thus, the path parameter’s shape_id value was the string "2" and not integer 2. So when the comparison was being made, it was trying to compare an integer to a string, and that will always be false, even if the string could be cast to the numeric equivalent.

05:13 What happens if no shape with the shape_id exists? Try to get a shape with an ID of 8 and see what happens.

05:24 Again, a null response. The expected outcome, according to REST, is to return a 404 status code, which means not found.

05:35 This is done by raising in HTTPException. In main.py, import the HTTPException class from the fastapi module. In the last line of the get_shape_by_id() function, raise the HTTPException with a status_code keyword argument of 404 and a detail keyword argument of "No shape with id {shape_id} found".

06:07 Save the code in the application we’ll restart.

06:14 In Swagger, try to get a shape with ID 8. This time the response has a 404 status code, and the body is JSON with the detail of the exception. By now, you are fairly well versed with how to handle GET requests in FastAPI.

06:33 Of course, GET is just one quarter of the story. In the next lesson, you will learn how to handle POST requests, and you’ll make more use of type hinting and pydantic to enforce the structure of the request body data.

Avatar image for Sandip Bhattacharya

Sandip Bhattacharya on Sept. 21, 2022

It would be great if the shapes array values was available to copy-paste from somewhere.

If it helps anywhere:

shapes = [
    {"item_name": "Circle", "no_of_sides": 1, "id": 1},
    {"item_name": "Triangle", "no_of_sides": 3, "id": 2},
    {"item_name": "Octagon", "no_of_sides": 8, "id": 3},
]

Become a Member to join the conversation.