FastAPI CRUD Example: A Simple Guide
FastAPI CRUD Example: A Simple Guide
Hey guys! Today, we’re diving into building a CRUD (Create, Read, Update, Delete) application using FastAPI, a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints. This guide will walk you through setting up a simple API that allows you to manage resources. Let’s get started!
Table of Contents
What is FastAPI?
Before we jump into the code, let’s quickly understand what makes FastAPI so awesome. FastAPI is designed with developer experience in mind, meaning it’s super easy to learn and use. It provides automatic data validation using Python type hints, generates OpenAPI and JSON Schema documentation out of the box, and has excellent performance. Plus, it’s fully compatible with async/await, making it perfect for building high-performance, asynchronous APIs.
FastAPI shines due to its speed and efficiency. It leverages Starlette and Pydantic under the hood, which are known for their performance. When you’re building APIs, especially those that need to handle a large number of requests, FastAPI’s performance benefits can be a game-changer. It reduces latency and improves the overall responsiveness of your application, leading to a better user experience. It also simplifies the development process with its intuitive design . You can define API endpoints, request and response models, and data validation rules using simple Python type hints. This eliminates a lot of boilerplate code and makes your code more readable and maintainable.
Another advantage of FastAPI is its automatic data validation. With Pydantic integration, you can define the expected data types for your API endpoints, and FastAPI will automatically validate incoming requests. If the data doesn’t match the expected types or constraints, FastAPI will return informative error messages to the client. This helps prevent invalid data from entering your application and reduces the risk of runtime errors. It generates OpenAPI and JSON Schema documentation automatically . This means you don’t have to manually write and maintain API documentation. FastAPI infers the API structure, request and response models, and data types from your code and generates interactive documentation that you can use to explore and test your API.
Prerequisites
Before we start coding, make sure you have Python 3.7+ installed. You’ll also need to install FastAPI and Uvicorn, an ASGI server that we’ll use to run our application. Open your terminal and run:
pip install fastapi uvicorn
These are the only dependencies we will need . FastAPI is the web framework itself, and Uvicorn is the server that will run our application. With these two packages installed, you’re ready to start building your API.
Setting Up the Project
Let’s create a new directory for our project and create a file named
main.py
. This is where we’ll write our FastAPI application code.
mkdir fastapi_crud
cd fastapi_crud
touch main.py
Inside the
fastapi_crud
directory, you can also create other files and subdirectories as needed
. For example, you might want to create a separate file for your database models or a directory for your tests. However, for this simple example, we’ll keep everything in the
main.py
file to keep things straightforward. Create a virtual environment to isolate your project dependencies. This helps prevent conflicts with other Python projects and ensures that your application has the correct dependencies. You can create a virtual environment using the
venv
module that comes with Python.
python3 -m venv venv
source venv/bin/activate # On Linux/Mac
.\venv\Scripts\activate # On Windows
Activating the virtual environment ensures that the
pip install
command installs the packages inside the virtual environment and not globally on your system
. Once you have created and activated the virtual environment, you can install FastAPI and Uvicorn using
pip install fastapi uvicorn
, as shown in the previous step.
Defining the Data Model
We’ll start by defining a simple data model using Pydantic, which is integrated with FastAPI. Let’s say we’re building an API to manage a list of items. Each item will have an
id
, a
name
, and a
description
.
Open
main.py
and add the following code:
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
id: int
name: str
description: Optional[str] = None
In this code, we’re importing the necessary modules from FastAPI and Pydantic
. We’re also defining a class called
Item
that inherits from
BaseModel
. This class defines the structure of our data model. Each item has an
id
of type
int
, a
name
of type
str
, and a
description
of type
Optional[str]
. The
Optional
type means that the
description
field is optional, and if it’s not provided, it will default to
None
.
Creating the CRUD Operations
Now, let’s define the CRUD operations for our API. We’ll start with creating a list to store our items in memory. In a real-world application, you’d likely use a database, but for this example, we’ll keep it simple.
Add the following code to
main.py
:
items = []
@app.post("/items/")
async def create_item(item: Item):
items.append(item)
return item
@app.get("/items/{item_id}")
async def read_item(item_id: int):
for item in items:
if item.id == item_id:
return item
return {"error": "Item not found"}
@app.put("/items/{item_id}")
async def update_item(item_id: int, updated_item: Item):
for index, item in enumerate(items):
if item.id == item_id:
items[index] = updated_item
return updated_item
return {"error": "Item not found"}
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
for index, item in enumerate(items):
if item.id == item_id:
del items[index]
return {"message": "Item deleted"}
return {"error": "Item not found"}
In this code, we’re defining five API endpoints:
create_item
,
read_item
,
update_item
, and
delete_item
. Each endpoint corresponds to a CRUD operation. The
@app.post
,
@app.get
,
@app.put
, and
@app.delete
decorators define the HTTP method and path for each endpoint. The
async
keyword indicates that these functions are asynchronous, which means they can handle multiple requests concurrently. The type hints for the function parameters and return values are used for data validation and serialization. The
create_item
endpoint creates a new item by appending it to the
items
list. The
read_item
endpoint retrieves an item by its ID. The
update_item
endpoint updates an existing item by its ID. The
delete_item
endpoint deletes an item by its ID. If an item is not found, the
read_item
,
update_item
, and
delete_item
endpoints return an error message.
Running the Application
To run the application, open your terminal and navigate to the project directory. Then, run the following command:
uvicorn main:app --reload
This command starts the Uvicorn server and tells it to run the
app
object in the
main.py
file
. The
--reload
flag tells Uvicorn to automatically reload the server whenever you make changes to the code. This is useful for development because you don’t have to manually restart the server every time you make a change.
Open your browser and go to
http://127.0.0.1:8000/docs
. You should see the automatically generated OpenAPI documentation for your API. You can use this documentation to test your API endpoints.
Testing the API
Now that our API is up and running, let’s test it out using the interactive OpenAPI documentation. Head over to
http://127.0.0.1:8000/docs
in your web browser. You should see Swagger UI, which provides a user-friendly interface for interacting with our API.
To test the
create_item
endpoint, click on the
POST /items/
endpoint and then click the “Try it out” button
. You can then enter the details for a new item in the request body, such as:
{
"id": 1,
"name": "Example Item",
"description": "This is an example item"
}
Click the “Execute” button to send the request. If everything goes well, you should see a
200 OK
response with the details of the newly created item.
To test the
read_item
endpoint, click on the
GET /items/{item_id}
endpoint and then click the “Try it out” button
. Enter the ID of the item you want to retrieve in the
item_id
field, such as
1
. Click the “Execute” button to send the request. If the item exists, you should see a
200 OK
response with the details of the item. If the item does not exist, you should see a
404 Not Found
response with an error message.
You can test the
update_item
and
delete_item
endpoints in a similar way
. Just make sure to enter the correct ID of the item you want to update or delete. If you encounter any issues, double-check your code and make sure that the server is running properly.
Conclusion
And there you have it! You’ve successfully built a simple CRUD API using FastAPI. This is just a starting point, but it gives you a solid foundation for building more complex APIs. FastAPI’s ease of use, automatic data validation, and excellent performance make it a great choice for building modern web APIs. Keep experimenting and exploring its features to unleash its full potential.
Remember, this example uses an in-memory list to store the items. In a real-world application, you’ll want to use a database to persist your data. FastAPI integrates well with various databases, such as PostgreSQL, MySQL, and MongoDB. You can use an ORM (Object-Relational Mapper) like SQLAlchemy or Tortoise ORM to interact with your database in a more Pythonic way.
Keep up the great work, and happy coding!