FastAPI Tutorial
- Why Use FastAPI?
- Install and Get Started with FastAPI
- GET and POST Routes
- Handling HTTP Errors
- JSON Request and Path Parameters
- Pydantic models
- Response Models
- Interactive Documentation
- FastAPI vs Flask vs Django
Why Use FastAPI?
- Easy to learn
- Fast development
- High performance (async by default)
Install and Get Started with FastAPI
- To install
FastAPI
, open the terminal and run the following command:
pip install fastapi uvicorn
Uvicorn
is the server that will be used ti test and run our FastAPI applications.
- Create a new directory for the project and create a file named
main.py
containing the following code:
from fastapi import FastAPI
# Create an app
app = FastAPI()
# define a path for HTTP Get method
@app.get("/")
def root():
return {"Hello": "World"}
- To run your server, use
uvicron
in the terminal:
uvicorn main:app --reload
--reload
option automatically refresh anytime you make changes to the file.
- Click the given URL http://127.0.0.1:8000 , you should be able to see the API route.
GET and POST Routes
In FastAPI, routes are used to define the different URLs that your app should respond to. You can create routes to handle different interactions.
For example, let’s build a to-do list
application. We’ll need different routes to add or view the to-do items on the list.
- In main.py, just after
app = FastAPI()
create an empty list of items:
items = []
- Next, create a new endpoint for our app (just after the root endpoint):
@app.post("items")
def create_item(item: str):
items.append(item)
return item
Users can access this endpoint by sending an HTTP Post request to this items path, and it’s going to accept
item
as an input (query parameter).
- To test the endpoint:
curl -X POST -H "Content-Type: application/json" 'http://127.0.0.1:8000/items?item=apple'
-
The same way, add an orange item.
-
Create an endpoint to view a specific item of the list, for that add the following code:
@app.get("items/{item_id}")
def get_item(item_id: int) -> str:
item = items[item_id]
return item
- To test the endpoint:
curl -X GET http://127.0.0.1:8000/items/0
- Now what happens if we try to get an item that doesn’t exist? go back to terminal and try:
curl -X GET http://127.0.0.1:8000/items/7
We get this error: Internal Server Error
, so we have to handle the error by raising useful error messages so we can debug it and figure out what went wrong.
Handling HTTP Errors
In FastAPI, it’s easy to raise specific errors to handle whatever situation you are dealing with. For example, to handle the last error sample (Internal Server Error).
There’s a universal set of HTTP response codes that we can use and every body will understand. If an item doesn’t exist, that’s usually a client error. Because the client is looking for a specific item that the server doesn’t know about.
It’s the 404 Not Found
code that has to be used to handle the item not found exception.
- To do that, import HTTPException from FastAPI:
from fastapi import FastAPI, HTTPException
- Then modify the get_item() endpoint to use the
HTTPException
:
@app.get("items/{item_id}")
def get_item(item_id: int) -> str:
if item_id < len(items):
return = items[item_id]
else:
raise HTTPException(status_code=404, detail=f"Item {item_id} not found")
- Run the same request again:
curl -X GET http://127.0.0.1:8000/items/7
We get:
{"detail" : "Item 7 not found"}
The error is updated to something more useful!
JSON Request and Path Parameters
Let’s see how we can send information to FastAPI.
- Create a new endpoint called
list_items
# this endpoint uses a query parameter 'limit'
@app.get("/items/")
def list_items(limit: int = 10):
return items[0:limit]
this function will return by default the first 10 items, or if limit=3, it will return the first 3 items.
- Test this endpoint (first add at least 10 items to the list):
curl -X GET 'http://127.0.0.1:8000/items?limit=3'
Pydantic models
FastAPI supports Pydantic
models which permit to structure data and also provide additional validation. This will make things like testing, documentation and code completion in your IDE easier.
Pydantic is the most widely used data validation library for Python. It lets you structure your data, gives you type-hints and auto-complete in your IDE, and helps to serialize to and from JSON.
- To get started, import
BaseModel
fromPydantic
:
from pydantic import BaseModel
- then after
app = FastAPI()
instruction add the following code that extend BaseModel to create an item class:
class Item(BaseModel):
text: str = None
is_done: bool = False
- Now update the app to use this Item model, so update
create_item
andget_item
to use Item model instead of str:
...
def create_item(item: Item):
...
def get_item(item_id: int) -> Item:
- Test the create_item endpoint (we have to send data as a JSON payload), so instead of:
curl -X POST -H "Content-Type: application/json" 'http://127.0.0.1:8000/items?item=apple'
use:
curl -X POST -H "Content-Type: application/json" -d '{"text":"apple"}' 'http://127.0.0.1:8000/items'
you will get this result:
[{"text":"apple","is_done":False}]
- We can change the text attribute of the Item class to be required like that:
class Item(BaseModel):
# without default value
text: str
is_done: bool = False
now if we try to add an item without a text value like the following (we put a title field instead) we will get an error, because it’s validating the request model and this’s another advantage of using Pydantic.
curl -X POST -H "Content-Type: application/json" -d '{"title":"apple"}' 'http://127.0.0.1:8000/items'
Response Models
So far, we’ve looked at how to model the request data and the input payload to FastAPI. Let’s look at how we can model the response as well. All we need to do is use the same base model from Pydantic for your response.
- Let’s update the app where we list items or where we get the item, all we have to do is add a new argument to the decorator called
response_model
:
...
# Specify the response type will be a list of Item
@app.get("/items", response_model=list[Item])
def list_item(limit: int = 10):
...
# Specify the response type will be an Item model
@app.get("/items/{item_id}", response_model=Item)
def get_item(item_id: int) -> Item:
This is very useful when we want to build a frontend client that interacts with FastAPI because we have a defined response structure.
Interactive Documentation
An other great feature of FastAPI is the interactive documentation. When ever you start a FastAPI server, you get a documentation page that you can interact with and use to test your API.
- To show the API documentation page, use this url: http://127.0.0.1:8000/docs
This will show the Swagger UI
page where you get to see all of your endpoints, which HTTP method they accept and if you click into them you can also look at the type of parameters they take. And you can test them.
- Also you can use http://127.0.0.1:8000/redoc to get another form of API documentation.
FastAPI vs Flask vs Django
-
FastAPI is:
- Async by default: it can handle more concurrent requests right out of the box.
- Easier to use: the way to define routes, response models, validate data and throw HTTP exceptions is as simple as it could be.
-
Flask is more complex
-
Django is a heavyweight framework.
By Wahid Hamdi