CRUD operations with FastAPI REST API

Posted by


In this tutorial, we will be building a RESTful API using FastAPI that performs CRUD operations (Create, Read, Update, Delete) on a simple resource, such as a list of books. FastAPI is a modern, fast web framework for building APIs with Python.

To get started, you will need to have Python installed on your machine. You can install FastAPI and other required dependencies by running the following command:

pip install fastapi uvicorn

Next, we will create a new Python file named main.py where we will define our FastAPI application. Let’s start by importing the necessary modules:

from fastapi import FastAPI
from pydantic import BaseModel

Next, we will create an instance of the FastAPI class and define a basic route for testing:

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello, World!"}

You can run the FastAPI application using the following command:

uvicorn main:app --reload

You should see output indicating that the server is running, and you can access it by visiting http://127.0.0.1:8000 in your web browser.

Now let’s define a simple data model for our books resource using Pydantic:

class Book(BaseModel):
    title: str
    author: str

Next, we will create an in-memory database to store our books data:

books = []

We will now define the CRUD operations for our API. Let’s start with the Create operation:

@app.post("/books/")
async def create_book(book: Book):
    books.append(book)
    return book

This route accepts a POST request with JSON data representing a new book, creates a Book object from the data using Pydantic, appends it to the books list, and returns the newly created book.

Next, let’s define the Read operation to retrieve all books:

@app.get("/books/")
async def get_books():
    return books

This route returns all the books stored in the database.

Now let’s define the Update operation to update an existing book by its index:

@app.put("/books/{index}")
async def update_book(index: int, book: Book):
    if index < len(books):
        books[index] = book
        return book
    else:
        return {"error": "Book not found"}

This route accepts a PUT request with JSON data representing the updated book and the index of the book to update. If the index is valid, the corresponding book is updated and returned. Otherwise, an error message is returned.

Finally, let’s define the Delete operation to delete a book by its index:

@app.delete("/books/{index}")
async def delete_book(index: int):
    if index < len(books):
        deleted_book = books.pop(index)
        return deleted_book
    else:
        return {"error": "Book not found"}

This route accepts a DELETE request with the index of the book to delete. If the index is valid, the corresponding book is deleted and returned. Otherwise, an error message is returned.

That’s it! You have now created a basic CRUD API using FastAPI. You can test the API using a tool like Postman by sending requests to the relevant endpoints (e.g., http://127.0.0.1:8000/books/) with the appropriate HTTP method and data.

This tutorial covers the basic CRUD operations, but you can extend the API further by adding authentication, validation, error handling, pagination, and more advanced features. FastAPI provides excellent documentation and features to help you build powerful and efficient APIs with Python.

0 0 votes
Article Rating

Leave a Reply

42 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@kvelez
15 days ago

from datetime import datetime

from typing import Text, Optional, List

from fastapi import FastAPI, HTTPException

from fastapi import Body

from pydantic import BaseModel, Field

from uuid import uuid4, UUID

class Post(BaseModel):

id: UUID = Field(default_factory=uuid4)

title: str

author: str

content: Text

created_at: datetime = Field(default_factory=datetime.now)

published_at: Optional[datetime] = None

published: bool = False

# Use a dictionary for in-memory database

posts_db: List[Post] = []

app = FastAPI()

@app.get("/")

async def main():

return {"message": "Hello World"}

@app.get("/posts/{post_id}", response_model=Post)

async def get_post(post_id: UUID):

for post in posts_db:

if post.id == post_id:

return post

raise HTTPException(status_code=404, detail="Post not found")

@app.get("/posts", response_model=List[Post])

async def get_posts():

return posts_db

@app.post("/posts", response_model=Post, tags=["posts"])

async def create_post(post: Post = Body(…)):

posts_db.append(post)

return post

@app.put("/posts/{post_id}", response_model=Post, tags=["posts"])

async def update_post(post_id: UUID, updated_post: Post = Body(…)):

for index, post in enumerate(posts_db):

if post.id == post_id:

updated_post.id = post_id # Ensure the ID remains the same

posts_db[index] = updated_post

return updated_post

raise HTTPException(status_code=404, detail="Post not found")

@app.delete("/posts/{post_id}", response_model=Post, tags=["posts"])

async def delete_post(post_id: UUID):

for index, post in enumerate(posts_db):

if post.id == post_id:

deleted_post = posts_db.pop(index)

return deleted_post

raise HTTPException(status_code=404, detail="Post not found")

@hannsflip
15 days ago

Gracias por la explicacion!!!

@kevinniebla1364
15 days ago

Los que le salga problema del 422 aunque lo tenga exactamente igual, se debe a que ahora tienes que definir Optional como None, id: Optional[str] = None y published_at : Optional[datetime] = None

@javierrivasseau8956
15 days ago

Hola Fazt como estas? Crees que es mejor Fast API + React + MongoDB que la tech MERN?

@diegosanabria695
15 days ago

A quienes les sale un error usando Optional al momento de hacer el post coloquen "= None" al final de cada Optional, puede ser por la version de Python 🤔. Esto permite que se hagan posts normalmente

@zasory
15 days ago

29:00 para los que tuvieron problemas en ese minuto finalmente di con la solucion , quizas en la version del profesor ermitira agregar el objeto (diccionario) como se lo permitia a el pero en versiones nuevas no y es que el esquema pide si o si datos y hay que especificar en case de que no, adjunto mi solución:

from fastapi import FastAPI

from pydantic import BaseModel #Modelo inicial, como van a lucir nuestros datos

from typing import Text, Optional

from datetime import datetime

from fastapi import HTTPException, status

from fastapi.encoders import jsonable_encoder

from uuid import uuid4 as uuid

app = FastAPI()

posts = []

# Post Model

class Post(BaseModel):

id: Optional[str] = None

title: str

author: str

content: Text

created_at: datetime = datetime.now()

published_at: Optional[datetime] = None

published: bool = False

@app.get('/')

def read_root():

return { "welcome":"welcome to my REST API" }

@app.get('/posts')

def get_posts():

return posts

@app.post('/posts')

def save_post(post : Post):

post.id = str(uuid())

post_dict = jsonable_encoder(post)

posts.append(post_dict)

return "recibido"

@tupapielrey3978
15 days ago

me trabe en la parte 29:00 me sigue saliendo error 422 help me

@jobadolfosalinashernandez265
15 days ago

Para Heroku me está pidiendo agregar un método de pago, tú cómo le hiciste para que no te cobrara?

@qwwrt8596
15 days ago

Buen video man, mejor que muchos cursos pagos

@hagoresumenes9224
15 days ago

-fazt ¿por que usas tab de 8 espacios?
-mis motivaciones van mas allá de tu entendimiento

@arthurblair6999
15 days ago

Buenas Fazt, como haces para recargar la consola? Yo le pico ctrl + c y vuelvo a ejecutar uvicorn app:app

@cristianezequiel815
15 days ago

Hola nesecito ayuda con el error 422 lo tengo igual que vos y no me deja hacer el post

@germanconil9475
15 days ago

Sin desperdicios !!! sos un crack!!!

@antoniopaz3575
15 days ago

FAZT muy buen video, la verdad siempre que busco algo que aprender, siempre estas tu, queria preguntarte, si puedes hacer un video sobre como hacer un CRUD con relaciones N:N con fastapi, o si ya hiciste un video que hables de ello, la verdad me ayudarias bastante, si cuentas con alguna comunidad de Fast API que me pueda ayudar, gracias de antemano, muy buenos videos

@Martin-vd6ux
15 days ago

Para los que no les deja utilizar el método post.dict(), utilicen post.model_dump() ya que post.dict() quedó obsoleto. Gracias por el video Fazt!

@nicoux9581
15 days ago

Muy bueno! Muchas gracias por compartir

@PonsianoDeLoor
15 days ago

muchas gracias Fazt un buen inicio con fastAPI

@VHSHORROR8
15 days ago

Hola video terminado-….heroku ya quito el metodo gratis o bueno de mi parte no lo encontre lo subire a github.. Gracias

@arnifuentes7055
15 days ago

Gracias Fazt!!!!

@eduardolopezcolmenero
15 days ago

Y este proyecto se podría deploy en serverless? Como a un lambda? O se tendría que desarrollar para lambda específicamente?

42
0
Would love your thoughts, please comment.x
()
x