Get AI summaries of any video or article — Sign up free
Python FastAPI Tutorial (Part 6): Completing CRUD - Update and Delete (PUT, PATCH, DELETE) thumbnail

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

Corey Schafer·
5 min read

Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

PUT updates posts as full replacements using required fields (title, content, user_id), while PATCH applies only provided fields using optional schemas.

Briefing

CRUD in FastAPI is completed for both posts and users by adding full update (PUT), partial update (PATCH), and deletion (DELETE), with careful request validation and REST-appropriate status codes. The key operational split is that PUT replaces an entire resource using a schema where all fields are required, while PATCH applies only the fields a client actually sends using optional fields plus logic that excludes “unset” values—preventing accidental overwrites (like wiping post content when only a title changes). For posts, the update flow also includes a 404 guard when the target post doesn’t exist, plus a check that a new user ID (if provided in PUT) refers to an existing user, avoiding database constraint errors and returning cleaner API responses.

Testing through the interactive docs confirms the behavior: PUT requires sending title, content, and user ID, and successfully changes ownership when the provided user exists. PATCH, by contrast, accepts only the changed fields (for example, updating just the title) and leaves other attributes untouched. Deletion follows standard REST conventions: DELETE returns 204 No Content on success, and subsequent GET requests for the deleted resource return 404 Not Found.

Users receive the same completion treatment, with a PATCH endpoint for partial profile updates. A new user update schema makes username, email, and image file optional (defaulting to none), while preserving validation rules when values are provided (e.g., email must be a valid email format, and image file name length is constrained). Update logic includes uniqueness checks: if a client tries to change a username or email to one already in use, the API returns 400 Bad Request rather than allowing a database error. After validation, only the provided fields are applied, then the updated user is committed, refreshed, and returned.

The most consequential data-model change is cascade deletion. When a user is deleted, SQLAlchemy is configured to delete all related posts automatically via cascade settings (including orphan cleanup). This mirrors common real-world “delete account” behavior where removing an account permanently removes associated content. After implementing the user DELETE endpoint (also returning 204), deleting a user is verified to remove their posts as well—confirmed by GET requests showing only remaining posts.

Finally, the tutorial demonstrates profile picture updates without adding file-upload capability yet. By adding an optional image file field to the user update schema and storing only the filename in the database, the application can compute the full image path dynamically in the models. Manually placing an image file into the media directory and then PATCHing the user’s image file updates the displayed profile picture on the homepage, while future work will add actual upload functionality.

Across both resources, the API uses consistent HTTP status codes (200, 201, 204, 400, 404, 422) and relies on Pydantic validation for request correctness, resulting in predictable behavior for client applications.

Cornell Notes

The API adds complete CRUD support for both posts and users in FastAPI. Posts get PUT for full replacement and PATCH for partial updates; the PATCH implementation uses optional fields plus “exclude unset” logic so missing fields don’t overwrite existing data. Both post and user DELETE endpoints return 204 No Content and raise 404 Not Found when the target resource doesn’t exist. User updates validate uniqueness for username and email and allow changing a profile picture filename, with the full image path computed from model properties. Cascade deletion is enabled so deleting a user automatically deletes all their posts, matching typical account-deletion behavior.

Why does PATCH need special handling to avoid wiping fields, and how is that achieved here?

PATCH uses a schema where fields are optional (defaulting to none). The endpoint then builds an update dictionary from the request body using a model dump with exclude_unset=True. That setting ensures only fields the client actually sent appear in the update payload; fields omitted by the client are excluded, so they don’t get applied as None and accidentally erase existing values like post content.

What’s the practical difference between PUT and PATCH for posts in this implementation?

PUT uses a “full update” schema where title, content, and user_id are required, so the client must send all fields and the endpoint replaces them on the post. PATCH uses the “partial update” schema with optional fields and dynamically sets only the provided attributes. As a result, PUT can change ownership (via user_id), while PATCH can update just one field (like title) without touching content.

How does the API prevent confusing database errors during post updates?

Before applying updates, it checks whether the post exists; if not, it raises 404 Not Found. For PUT, it also checks whether a new user_id exists when the client attempts to change ownership. This avoids letting foreign-key constraints fail and instead returns a clearer, intentional error path.

What uniqueness rules are enforced when updating users, and what happens when they’re violated?

When PATCHing a user, the endpoint checks whether a new username or email already exists in the database. If the requested username or email is already taken, it returns 400 Bad Request rather than allowing the update to proceed. Only after passing these checks does it apply the provided fields, commit, refresh, and return the updated user.

How does cascade deletion work here, and what outcome does it guarantee?

SQLAlchemy relationship settings are updated so that when a user is deleted, all posts related to that user are deleted automatically (cascade delete with orphan cleanup). The DELETE /users endpoint returns 204, and subsequent GET requests confirm the user’s posts are gone—ensuring account deletion removes associated content.

How can profile pictures be updated without file uploads in this setup?

The user update schema includes an optional image file field. The database stores only the filename, while a model property computes the full image path used by templates. By manually placing an image file into the expected media directory and then PATCHing the user with the filename, the homepage reflects the new profile picture. Upload UI is deferred to a later tutorial.

Review Questions

  1. When implementing PATCH, what does exclude_unset=True prevent, and what bug would occur without it?
  2. In what situations should a 404 Not Found be raised during update or delete operations for posts and users?
  3. How does cascade deletion change the expected results of deleting a user, and how would you verify it with GET requests?

Key Points

  1. 1

    PUT updates posts as full replacements using required fields (title, content, user_id), while PATCH applies only provided fields using optional schemas.

  2. 2

    PATCH correctness depends on exclude_unset=True so omitted fields don’t get overwritten with default None values.

  3. 3

    Update endpoints include existence checks for the target resource and, for post ownership changes, validation that the referenced user exists.

  4. 4

    DELETE endpoints return 204 No Content on success and 404 Not Found when the resource doesn’t exist.

  5. 5

    User PATCH enforces uniqueness for username and email, returning 400 Bad Request when a requested value is already in use.

  6. 6

    Cascade deletion is configured so deleting a user automatically deletes all their associated posts.

  7. 7

    Profile picture updates are supported by PATCHing an image filename and computing the full path from model properties, with uploads added later.

Highlights

PUT requires sending all post fields, including user_id, enabling ownership changes in one request.
PATCH avoids accidental data loss by excluding unset fields from the update payload before applying changes.
Cascade deletion ensures user account deletion removes all related posts automatically.
Profile pictures can be updated immediately by changing the stored filename, even before adding upload functionality.

Topics

Mentioned