FastAPI: Build RESTful, Fast APIs With Python
Great Python web frameworks make it easy to create high functioning and scalable applications. Many web frameworks are heavy, monolithic (old) frameworks that make modern-day development practices difficult to solve that are not optimal for creating fast APIs. With the rise of RESTful web APIs (Representational State Transfer – Application Programming Interfaces), there is not a better time to learn how to create secure and maintainable applications. FastAPI is a modern Python web framework for building APIs that is getting rid of the old ways of doing development. Just one of the many things Python is used for and does well.
FastAPI benefits
What are the benefits of using FastAPI? I am glad you asked. There are many technical, user, and development benefits when choosing FastAPI to be your go-to framework for modern Python web development. Here are some quick key notes:
FastAPI is FAST
Since FastAPI is built off of Starlette and Pydantic, the performance of FastAPI is off the charts. In fact, FastAPI’s performance has been tested to be on par with NodeJS.
FastAPI makes creating APIs simple
Developing APIs used to be a very technical process that required a tremendous amount of development time. FastAPI has helped shift that mindset. FastAPI is an intuitive framework that allows you to write production worthy RESTful APIs in the matter of minutes.
FastAPI comes with interactive documentation
When you create a FastAPI application, an interactive Swagger UI documentation is created automatically. This increases the performance of Python developers, as they no longer have to handle documentation. This means developers can focus on one thing, the code, and let FastAPI handle everything else.
Good to know RESTful API information
RESTful APIs communicate by way of HTTP (Hypertext Transfer Protocol) to perform standard functionalities, which include creating, reading, updating, and deleting a resource. These are also known as the CRUD operations. To correspond with these CRUD operations, HTTP has request methods that provide us the action counterpart. These HTTP counterparts are called GET, POST, PUT, PATCH, and DELETE. A list of the CRUD operations aligned with the HTTP request method counterparts include:
- Create – Uses the HTTP POST request method.
- Read – Uses the HTTP GET request method.
- Update – Uses the PUT/PATCH request method.
- Delete – Uses the DELETE request method.
Last Updated September 2023
Dive in and learn FastAPI from scratch! Learn FastAPI, RESTful APIs using Python, SQLAlchemy, OAuth, JWT and way more! | By Eric Roby
Explore CourseProject: Building a list of book objects
To learn and explore FastAPI, we will be building a list of Book objects, where each Book object will have its own ID identifier, title, author, description, and rating. We will be going over all CRUD operations and how we can quickly create scalable RESTful APIs using Python. To get a idea of what we will do in this beginner project, here is the list of steps:
- Install FastAPI and related dependencies
- Create our first RESTful API using the GET request method
- Learn about Swagger UI Documentation to test and use our APIs
- Learn how to use path parameters within FastAPI
- Develop a book class/object using Pydantic to perform rapid data validation
- Create new books using the POST request method
- Read all books within a list using the GET request method
- Update books using the PUT request method
- Delete books using the DELETE request method
We will be building a books project, but after this tutorial, you can create just about anything you want using FastAPI and Python. This tutorial will give you the tools needed to start your development journey using a modern development approach. If you need help thinking of some Python-based ideas, check out our blog post with 9 Python project ideas.
Getting started building a fast API
There are some requirements before you can use FastAPI. However, there are only three requirements for you, the developer, to get started! Those include:
- Python 3.6+
- FastAPI
- Uvicorn
To install FastAPI:
- Create a new directory on your machine. Mine will be called “FastAPI”.
- Jump in your favorite terminal or command prompt and type:
pip install fastapi
After the FastAPI installation, you will need an Asynchronous Gateway Interface (ASGI). This is just a fancy way of saying we need an interface that is async-capable for Python web servers and applications. You can read more about that here. We can install an ASGI by typing:
pip install "uvicorn[standard]"
And just like that, you have a FastAPI application! Well, kinda. You have a FastAPI application with no code. Let’s add some functionality to really make use of the FastAPI framework!
Let’s write some code
If you are a visual learner, you can watch an entire introduction to FastAPI on YouTube to learn more about it. Before we write some code, let’s create a new Python file called “books.py”. After creating a books.py file, our directory structure should look like the below.
We have our directory of “FastAPI” with “books.py” within it. Now for the fun part, let’s see how fast we can create RESTful APIs! Within our books.py file, let’s type:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_api():
return {"Welcome": "Eric"}
We start by importing our FastAPI framework that we downloaded with pip. We are creating an object that is equal to FastAPI(), which we are naming app. Nice work! We now have FastAPI all connected within our application. Yes, you read that right! FastAPI is all connected within your application with only two lines of code.
We are then using an annotation (@) to connect our app object to the beginning of our function, and calling the GET HTTP request method, which is the Read functionality when dealing with RESTful APIs. We also clarify that we are calling the Read functionality, by naming the Python function read_api, which returns a simple dictionary with “Welcome” as the key and “Eric” as the value. We will be changing what the dictionary returns later on, but for now, let’s run the app and kick off our FastAPI application.
Top courses in Python
How to run your FastAPI application
To start our application, jump into your terminal and project directory and type:
uvicorn books:app --reload
The command we typed in the terminal is pretty simple once you understand what is going on.
- uvicorn is the ASGI we are referring to
- books is the python file we created
- app the object we created inside the books file that refers to FastAPI()
- –reload this causes a server reset after each code change so our application us up to date
You should now see a lot of information being put within your terminal:
If you get the message “Application startup complete”, this means your application has successfully started. We initialized uvicorn and the books file that contains the “app” object. We added “–reload”, which reloads the application server each time a change happens; however the “–reload” is not needed. One of the key pieces of information we can see in the terminal is “Uvicorn running on 127.0.0.1:8000”.
Now open up your favorite internet browser and type and go to http://127.0.0.1:8000. The first thing you should see is your GET API returned as JSON (JavaScript Object Notation).
We can see in my browser our dictionary formatted as JSON, with “Welcome” as the key and “Eric” as the value.
For some more fun tech, you can right-click your internet browser page and click inspect. From here, navigate over to network and refresh your screen. Here, you will be able to see your browser call the RESTful API you just created. Pretty awesome!
Interactive Swagger UI documentation
Let’s now take a look at how FastAPI has an interactive Swagger UI documentation automatically embedded within the application. Browse to http://127.0.0.1:8000/docs to see this.
Immediately, we can see we have a GET Request Method. If we click on the specific API within the Swagger UI documentation, we will see even more information.
Here we can see that our API requires no parameters, and a successful response includes a media type of application/json within a string value. Using FastAPI, we were able to create a GET HTTP request method using only a few lines of code. This is the power of FastAPI.
Python students also learn
Path parameters
Next, we will enhance our GET request method to use a path parameter. Path parameters are added in the path of an endpoint and can be used within our API function. Instead of the value “Eric” being declared, let’s change this to a path parameter so that we can pass any value to the dictionary. To do this:
- We will add a {name} at the end of our GET endpoint.
- We will pass in name: str as a parameter to our function.
- Finally, we return the name variable within the dictionary value.
@app.get("/{name}")
def read_api(name: str):
return {"Welcome": name}
If we jump back into our Swagger UI Docs, we will now be able to pass in a value of name and execute the API! Path parameters are used a lot, and probably more times than not, are used for passing around the primary keys of an object. So far, we have created GET request methods. How do we pass in larger pieces of data to be consumed by the API, and how do we validate the data? For this, we will use the POST request method and pydantic.
Data validation with pydantic
Pydantic allows for data validation by adding type hints at runtime and giving the developer easy to read errors when data is invalid. Since we will be adding book objects to our application, let’s go ahead and add pydantic to our application by import:
from pydantic import BaseModel, Field
Now that we have imported pydantic, let’s go ahead and add a Book class to our application.
class Book(BaseModel):
id: UUID
title: str = Field(min_length=1)
author: str = Field(min_length=1, max_length=100)
description: str = Field(min_length=1, max_length=100)
rating: int = Field(gt=-1, lt=101)
Since pydantic is all about data validation, we will be using pydantic specific fields to describe how we want our new class object to operate. Within our new Book object we want there to be:
- An id of type UUID (Universally Unique Identifiers).
- A title of a book to be of type string. We will also use a pydantic field to specifically say the title’s minimal length must be 1.
- We also want the book to have an author of type string, where we are specifically saying the author’s name must be between 1 and 100 characters long.
- We want the book to have a description of type string that must be between 1 and 100 characters long.
- Finally, our book must have a rating which must be greater than -1, and less than 101, which in reality gives us a rating between 0 and 100.
After creating the class Book, let’s create an empty list called BOOKS:
BOOKS = []
So as of right now, our code should look like:
POST request method
Now under our function read_api, let’s create a new function called create_book that will take in our Book class as a parameter and has a post annotation above. The create_book function will append the new book to the empty list BOOKS we created and return the book back to the user:
@app.post("/")
def create_book(book: Book):
BOOKS.append(book)
return book
While we are here, let’s also modify our read_api to return the list of Books we created. We will also remove all path parameters and function parameters from our read_api function.
@app.get("/")
def read_api():
return BOOKS
Let’s now jump back into our Swagger UI Docs by visiting http://127.0.0.1:8000/docs, and we can see a new API called Create Book. Inside the new Post request, we can see the Request Body is a mandatory field. At the top click “Try it out”, where we can now customize our entire request body.
At first glance, we can see that FastAPI automatically provides dummy information to submit a request. FastAPI automatically knows what needs to be passed in this request based on the Books object we created. The Books object is a required parameter for the function. Lets customize our title, author, description, and rating to match below.
The book will contain:
- id : random generated UUID
- title : “Eric’s FastAPI Course”
- author : “Eric Roby”
- description : “The quickest way to learn FastAPI”
- rating : 100
Go ahead and click execute, and we can see immediately that our book was submitted and passed all data validation protocols from pydantic. If we change our rating from 100 to 110, we can see that we get an error code of 402 with the error stating “Unprocessable Entity”.
Now this is the true power of pydantic. Pydantic did some data validation, compared it to our Book Class, which only allows rating to be between 0 and 100, and sent back an error, without us having to do any data validation ourselves – pretty awesome!
Now, let’s run our new “Read API” (the one that returns all books) and execute this API. We will see our response body to be holding our new book we submitted:
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"title": "Eric's FastAPI Course",
"author": "Eric Roby",
"description": "The quickest way to learn FastAPI",
"rating": 100
}
]
Let’s go ahead and make another new book! For this new book, I will be submitting an example book with an example author just for demonstration purposes. However, we must make sure our UUID is different from the one in our original book.
The example book will contain:
- id : random generated UUID
- title : “Example Title”
- author : “Example Author”
- description : “Example Description”
- rating : 90
After we create our second book, our GET request method should return both books as a list:
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"title": "Eric's FastAPI Course",
"author": "Eric Roby",
"description": "The quickest way to learn FastAPI",
"rating": 100
},
{
"id": "4eb85f64-5717-4562-b3fc-2c963f66afa5",
"title": "Example Title",
"author": "Example Author",
"description": "Example Description",
"rating": 90
}
]
Hmm, the description for the first book currently says “The quickest way to learn FastAPI”. I think it sounds better if we changed this to “The fastest way to learn FastAPI”. Let’s switch back to our IDE (integrated development environment) and start writing some code.
Featured courses in Web Development
PUT request method and HTTPExceptions
First, let’s add a new import at the top of our code that can raise HTTPExceptions. This new import is from FastAPI, so we are just adding the HTTPException at the end of the import.
from fastapi import FastAPI, HTTPException
Once our import is in under our POST request method, create a new function called, update_book. This function will take in a path parameter of a UUID and a book request body. We will also be adding an annotation at the top of our function clarifying that this function is a PUT request method along with using book_id as a path parameter.
@app.put("/{book_id}")
def update_book(book_id: UUID, book: Book):
counter = 0
for x in BOOKS:
counter += 1
if x.id == book_id:
BOOKS[counter - 1] = book
return BOOKS[counter - 1]
raise HTTPException(
status_code=404,
detail=f"ID {book_id} : Does not exist."
)
What is this code doing? We are looping through BOOKS to see if any of the book’s UUID matches the book_id path parameter. If there is a match, we will swap out the data of the book and return the book that the API requested. If there is no match, we will raise an HTTPException, returning a status code of 404 with information explaining how the book UUID does not exist. Let’s now go back into our Swagger UI Documentation, where we will see a new PUT request method.
Now, open our new PUT request method and pass in the UUID: 3fa85f64-5717-4562-b3fc-2c963f66afa6. This is the UUID of a book we already created. We will then need to add our original book to the request body with the changes to the description.
After we click execute, we can jump back into our GET request, and we will see that our book changed from “The quickest way to learn FastAPI”, to “The fastest way to learn FastAPI”.
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"title": "Eric's FastAPI Course",
"author": "Eric Roby",
"description": "The fastest way to learn FastAPI",
"rating": 100
},
{
"id": "4eb85f64-5717-4562-b3fc-2c963f66afa5",
"title": "Example Title",
"author": "Example Author",
"description": "Example Description",
"rating": 90
}
]
DELETE request method
Alright, now for the fun part. Let’s create a RESTful API to delete the example book. Under our update_book functionality, let’s go ahead and create a new function called delete_book. This function will take in a UUID as a parameter, so we know which book to delete. We will also need to put a delete annotation above the function that takes in a book_id as a path parameter.
@app.delete("/{book_id}")
async def delete_book(book_id: UUID):
counter = 0
for x in BOOKS:
counter += 1
if x.id == book_id:
del BOOKS[counter - 1]
return f'ID:{book_id} deleted'
raise HTTPException(
status_code=404,
detail=f"ID {book_id} : Does not exist."
)
The function we created will delete a book if the book.id matches the path parameter UUID, and if not, it will return a dictionary with the book_id, saying that the specific UUID does not exist. When we open our Swagger UI Docs, we should now have four RESTful APIs to choose from:
Let’s open up our delete API and pass in the UUID of 4eb85f64-5717-4562-b3fc-2c963f66afa5, to delete the example book.
After we execute the delete functionality, our GET request API will only display a single book, due to the example book being deleted:
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"title": "Eric's FastAPI Course",
"author": "Eric Roby",
"description": "The fastest way to learn FastAPI",
"rating": 100
}
]
And there we have it! We created a functional application using FastAPI. We created the application using RESTful APIs while implementing the HTTP request methods of GET, POST, PUT, and DELETE. FastAPI allows you to create RESTful APIs quickly!
Continued learning
FastAPI is great for building APIs with Python. To learn about Python frameworks for building complete web applications, check out Udemy’s blog post on Django, the post on Flask versus Django, and these Python project ideas.
To really take your FastAPI knowledge to the next level, check out my Udemy master course where we cover all things FastAPI, which includes:
- Authentication
- Authorization
- JWT
- Security
- Full Stack
- Databases
- And more!
Cheers friends and happy learning!