Python API Development with FastAPI
FastAPI Basics
Updating Posts
In this lesson, we complete the CRUD operations by implementing the update functionality using the HTTP PUT method. Building on the DELETE operation structure, this guide explains how to update a post by sending a complete payload that follows the defined schema.
Setting Up a New Request in Postman
Begin by creating a new request in Postman using the same URL structure as for deleting a post (e.g., /posts/{id}
). When updating a post, your request body must include all data fields defined in the post schema: title, content, a published flag, and an optional rating.
For instance, sending only a title like the example below will not work with the PUT method because it expects data for every field:
{
"title": ""
}
Instead, when updating the title, the complete request body should look like:
{
"title": "updated title",
"content": "content of post 1",
"published": true,
"rating": null
}
Understanding the FastAPI Application
The following snippet shows a basic FastAPI application that defines a Post model and stores posts in a list. Notice the helper functions used to locate posts by their ID.
from typing import Optional
from fastapi import FastAPI, Response, status, HTTPException
from pydantic import BaseModel
from random import randrange
app = FastAPI()
class Post(BaseModel):
title: str
content: str
published: bool = True
rating: Optional[int] = None
my_posts = [
{"title": "title of post 1", "content": "content of post 1", "id": 1},
{"title": "favorite foods", "content": "I like pizza", "id": 2}
]
def find_post(id: int):
for post in my_posts:
if post['id'] == id:
return post
def find_index_post(id: int):
for index, post in enumerate(my_posts):
if post['id'] == id:
return index
return -1
Note
Ensure that the Postman request body is set as raw JSON. The initial test might just update a single field, but remember to include all required fields for a successful update.
Testing the Update Operation in Postman
When testing in Postman, if you attempt to update only one field with:
{
"title": "updated title"
}
you will encounter issues because the PUT method requires the complete post data. For example, if the original Post 1 is structured as:
my_posts = [
{"title": "title of post 1", "content": "content of post 1", "id": 1},
{"title": "favorite foods", "content": "I like pizza", "id": 2}
]
Then, to update Post 1, your request body must include all required fields:
{
"title": "updated title",
"content": "content of post 1",
"published": true,
"rating": null
}
The DELETE Operation for Context
Below is the DELETE endpoint implementation that removes a post based on its ID:
@app.delete("/posts/{id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_post(id: int):
index = find_index_post(id)
if index == -1:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Post with id: {id} does not exist"
)
my_posts.pop(index)
return Response(status_code=status.HTTP_204_NO_CONTENT)
Implementing the PUT Operation
The new PUT operation checks whether the post exists using the find_index_post
helper function. If the post is not found, it raises a 404 error; otherwise, it updates the post by replacing the old values with the new data while preserving the original ID.
@app.put("/posts/{id}")
def update_post(id: int, post: Post):
index = find_index_post(id)
if index == -1:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Post with id: {id} does not exist"
)
post_dict = post.dict()
post_dict['id'] = id
my_posts[index] = post_dict
return {"data": post_dict}
When you run the application, your terminal will log information similar to the following, confirming that the update operation is working:
INFO: title='updated title' content='content of post 1' published=True rating=None
INFO: 127.0.0.1:64051 - "PUT /posts/1 HTTP/1.1" 200 OK
Verifying the Update
After updating a post (for example, changing the title to "updated title" and content to "This is the new content"), you should receive a response like:
{
"data": {
"title": "updated title",
"content": "This is the new content",
"published": true,
"rating": null,
"id": 1
}
}
To confirm, perform a GET request on /posts
. The updated list of posts should display the modified data:
{
"data": [
{
"title": "updated title",
"content": "This is the new content",
"published": true,
"rating": null,
"id": 1
},
{
"title": "favorite foods",
"content": "I like pizza",
"id": 2
}
]
}
Note
Review the JSON response in Postman to ensure every post object includes all the expected fields. This helps verify that the data is persisted correctly.
Next Steps
After confirming the update operation, all CRUD operations have been successfully implemented in the FastAPI application. In the next lesson, we will refactor the code for enhanced readability and maintainability before integrating a PostgreSQL database to persist the data.
Transcribed by https://otter.ai
Watch Video
Watch video content