Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 27

Building a DELETE Endpoint

Recommended resources

Welcome back! In the last lesson, we mastered the "Update" part of CRUD, implementing a PATCH endpoint to modify existing records. With create, read, and update operations in place, our API is almost complete.

This lesson focuses on the final piece of the puzzle: D for Delete. You will learn how to implement an endpoint that permanently removes a record from the database. This is the last fundamental operation needed to give you full control over your data via the API.

We will cover the standard HTTP DELETE method, the correct status code to return for a successful deletion, and how to write the corresponding FastAPI path operation to interact with your SQLAlchemy database.

The DELETE Operation

The DELETE method is straightforward: its purpose is to delete a specific resource. Just like our GET (single item) and PATCH endpoints, a DELETE request typically identifies the resource to be removed using a path parameter, such as an ID.

The logical flow for a delete operation is simple and should feel familiar:

  1. Receive a request to a path like /items/{item_id}.
  2. Find the item in the database with that ID.
  3. If the item doesn't exist, return a 404 Not Found error.
  4. If it does exist, remove it from the database.
  5. Signal that the deletion was successful.

The 204 No Content Status Code

A key convention in REST API design relates to the response from a DELETE request. Since the resource has been removed, there's nothing to send back in the response body.

The standard way to signal a successful deletion is with the HTTP status code 204 No Content. This code tells the client, "I did what you asked, and it was successful, but I have no data to give you in return."

FastAPI makes it easy to set this as the default status code for an endpoint.


Implementing the DELETE Endpoint

Let's translate this logic into code. The implementation is very similar to the start of our update_item function, but it ends with a deletion instead of an update.

The following video from Corey Schafer, which you've seen before, provides a concise walkthrough of creating a DELETE endpoint.

Python FastAPI Tutorial (Part 6): Completing CRUD - Update and Delete (PUT, PATCH, DELETE)

Watch this clip to see how to implement a DELETE path operation in FastAPI, including setting the status code to 204 No Content.

Watch from 15:57 to 18:55. Pay attention to the @app.delete decorator, the check for a 404 error, and how the db.delete() and db.commit() calls work together.

Now, let's add the DELETE endpoint to your main.py file. The code follows the exact pattern shown in the video.




# In main.py
# ... other imports
from fastapi import status # Import the status module




# ... your app setup and other endpoints ...

@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(item_id: int, db: AsyncSession = Depends(get_db)):



    # 1. Get the existing item from the database
    db_item = await db.get(models.Item, item_id)
    if not db_item:
        raise HTTPException(status_code=404, detail="Item not found")




    # 2. Delete the item from the session
    await db.delete(db_item)
    



    # 3. Commit the transaction to the database
    await db.commit()
    



    # 4. No response body is returned due to the 204 status code
    return

Let's break down the key parts of this code:

  • @app.delete("/items/{item_id}", ...): We use the @app.delete decorator to register this function to handle DELETE requests to the specified path.
  • status_code=status.HTTP_204_NO_CONTENT: This is how you tell FastAPI that the default response for a successful request should be 204. You import status from fastapi to get access to a full list of HTTP status codes.
  • await db.get(...) and HTTPException: This is the same logic we used in the update and retrieve endpoints to find the record or return a 404 error if it's missing.
  • await db.delete(db_item): This is the core SQLAlchemy async command. It stages the db_item object for deletion within the current database session. The record isn't actually deleted from the database yet.
  • await db.commit(): This command finalizes the transaction, permanently deleting the record from the database table.
  • return: Because we've set the status code to 204, FastAPI knows not to expect a response body. A simple return or returning None is sufficient. You don't need a response_model here.

For another perspective, this article from the official SQLModel tutorial shows the exact same logic in a synchronous context.

Delete Data with FastAPI - SQLModel

This page from the SQLModel documentation provides a clear, textual explanation of the delete operation.

Read the section "Delete Path Operation". Notice that the core logic—find the object, delete it from the session, then commit—is identical. This example returns a JSON object {"ok": True} with a default 200 OK status, which is an alternative to 204 No Content. Both are valid, but 204 is more common for DELETE.


Testing Your DELETE Endpoint

Now that you've added the code, it's time to test it and see it in action.

  1. Make sure your Uvicorn server is running.
  2. Open your browser to http://127.0.0.1:8000/docs.
  3. First, use the POST /items/ endpoint to create a new item. Note its ID.
  4. (Optional) Use the GET /items/{item_id} endpoint with the new ID to confirm it was created successfully.
  5. Now, expand the DELETE /items/{item_id} endpoint.
  6. Click "Try it out", enter the ID of the item you just created, and click "Execute".

You should see a 204 response code and "No content" in the response body section.

FastAPI DELETE Request in Swagger UI
This screenshot shows a successful delete request in the Swagger UI. The server responded with a success code (200 in this example, but you will see 204) and no response body, confirming the deletion.

To be absolutely sure, try using the GET /items/{item_id} endpoint again with the same ID. This time, you should receive a 404 Not Found error, proving the record is gone.


Beyond Simple Deletion: Soft Deletes

In many real-world applications, especially those where data integrity and history are important, records are rarely deleted permanently from the database. Instead, a "soft delete" is performed.

A soft delete typically involves marking a record as inactive rather than removing it. This is often done by setting an is_deleted boolean flag to True or populating a deleted_at timestamp. Your API's "read" queries would then be updated to filter out these "deleted" records.

This approach has several advantages:

  • Data Recovery: You can easily "undelete" a record.
  • Auditing: You maintain a full history of all data, which can be crucial for compliance and analytics.
  • Referential Integrity: Other records that point to the "deleted" record don't break.

You don't need to implement this now, but it's an important concept to be aware of as you build more complex, production-ready systems. The fastapitutorial.com blog provides a good, brief explanation of this concept. You can find it under the "Alternative Approaches" section in the article "Delete a Model Object using SQLModel" (ID: [LINK](https://fastapitutorial.com/blog/delete-model-object-sqlmodel-fastapi/)).


Conclusion

Excellent work! You have now implemented all four CRUD operations—Create, Read, Update, and Delete. You have a complete, functioning REST API for managing a resource in your database. This is a foundational skill for any backend developer.

Key Takeaways:

  • The HTTP DELETE method is used to remove a resource.
  • The standard success response for a DELETE operation is 204 No Content, indicating success without a response body.
  • You can set the status code in FastAPI with the status_code argument in the decorator (e.g., @app.delete(..., status_code=status.HTTP_204_NO_CONTENT)).
  • The database logic involves fetching the record, calling db.delete() on it, and then calling db.commit() to finalize the deletion.
  • "Soft deletes" are a common pattern in production applications to preserve data history and allow for recovery.

In the next lesson, we will address a small but important security detail: how to prevent sensitive information, such as user passwords or internal flags, from being accidentally exposed in your API responses using response_model_exclude.