This article discusses refactoring FastAPI code to align with RESTful principles and standardizing API endpoint naming conventions.
In previous examples, we discussed best practices and naming conventions for building APIs. In this updated guide, our FastAPI code is refactored to align with RESTful principles and industry standards.
Initially, our application defined GET and POST endpoints as follows:
Copy
Ask AI
@app.get("/")def root(): return {"message": "Hello World"}@app.get("/posts")def get_posts(): return {"data": "This is your posts"}@app.post("/createposts")def create_posts(post: Post): print(post) print(post.dict()) return {"data": post}
Notice that the POST endpoint is defined with the path /createposts, which is inconsistent with RESTful naming standards. Our goal is to standardize all endpoints, so we update the POST endpoint to use /posts.
After updating the endpoint, be sure to adjust your testing tools—such as Postman—with the new endpoint URL. For example, sending the following JSON in a POST request:
Since this simple example does not use a database, we simulate data persistence by storing posts in an in-memory list. In a production setting, these posts would be saved to a database where ID creation is handled automatically. Here, we assign a unique ID to each post using a random integer.Below is the consolidated version of our FastAPI application:
Copy
Ask AI
from typing import Optionalfrom fastapi import FastAPIfrom pydantic import BaseModelfrom random import randrangeapp = FastAPI()class Post(BaseModel): title: str content: str published: bool = True rating: Optional[int] = None# In-memory storage for postsmy_posts = [ {"title": "title of post 1", "content": "content of post 1", "id": 1}, {"title": "favorite foods", "content": "I like pizza", "id": 2}]@app.get("/")def root(): return {"message": "Hello World"}@app.get("/posts")def get_posts(): return {"data": my_posts}@app.post("/posts")def create_posts(post: Post): # Convert the Pydantic model to a dictionary post_dict = post.dict() # Assign a unique ID using a random number for demonstration purposes post_dict['id'] = randrange(0, 100000) my_posts.append(post_dict) # Return the newly created post including its ID return {"data": post_dict}
Data Model:
The Post class (a Pydantic model) defines the structure and validation rules for incoming post data.
In-Memory Storage:
The my_posts list simulates a database and is pre-populated with two sample posts. Note that any data stored here will be lost when the server restarts.
GET Endpoint:
The /posts GET endpoint returns all stored posts in response to client requests.
POST Endpoint:
The /posts POST endpoint validates the input post using the Post model, converts it to a dictionary, assigns a unique ID using randrange, appends the post to the in-memory list, and returns the new post data.
When you test the GET endpoint (using Postman, for example), you should see a response similar to this:
Copy
Ask AI
{ "data": [ { "title": "title of post 1", "content": "content of post 1", "id": 1 }, { "title": "favorite foods", "content": "I like pizza", "id": 2 } ]}
As you continue to enhance your API, consider incorporating input validation and error handling mechanisms to build a fully functional CRUD-based application.
By following these guidelines, you ensure your API is both maintainable and aligned with RESTful best practices.