Module 4 of 9 · Lesson 8 of 26
Persist CRUD changes with explicit transactions
Work through persist CRUD changes with explicit transactions using a runnable reference, a focused regression check and a local extension.
Read in any order. All lessons stay open, including after an unanswered or incorrect check.
Rollback matters when a later operation fails. The lesson changes an existing item and attempts a duplicate name in the same transaction. PostgreSQL rejects the duplicate; the earlier name change must also disappear. Separate commits would preserve that partial update and violate the request's promise. PATCH uses exclude_unset so untouched fields stay unchanged, and explicit null is rejected where the schema cannot accept it. A transaction context owns commit and rollback; lower-level helper functions should not introduce surprise commits. When catching a database error, finish or roll back the failed transaction before using the session again. Return a stable conflict, rather than pretending that a partially applied operation succeeded.
The integrated routes also read equipment and delete only equipment with no rental history. Deletion locks the parent and rejects any referenced item with 409; it never erases a rental to make deletion succeed. The final endpoint integration check exercises create, read, update and this safe deletion rule.
Read create_equipment and patch_equipment in services.py. The lesson08 check reads a created item through a new session, forces a later uniqueness failure, and confirms the earlier change rolled back. It also rejects explicit null. Notice which assertions would still pass after flush alone and which require committed visibility.
def create_equipment(session, data):
with session.begin():
item = Equipment(**data.model_dump())
session.add(item)
session.flush()
result = EquipmentOut.model_validate(item)
return result # commit completed before the caller can send success
python run_checks.py -k lesson08
Expected result The selected lesson test passes against a new temporary PostgreSQL database; the container is removed afterward.
Keep for reference
Equipment Rental lab and lesson checks
ZIP containing Python source, real Alembic migrations, 26 lesson checks, a dependency lock and text instructions. Extract it before following the local exercise.
Practise locally
Add a service that updates an item's name and daily rate together. Force the second operation to fail in a test and verify both old values remain. Add a successful test using a new session to read the committed result. Keep the commit at the service boundary and record the full response contract, including the conflict path.
The lesson check verifies the reference behavior. Add your own assertions for your change. Local practice is not uploaded or scored by this learning release.
Pause and reflect
What failure does this lesson prevent, and which assertion in lesson08 would expose it?
Use a concrete input, expected result and limitation from your local work. Saving a reflection does not certify the project.
Optional knowledge check
What does flush guarantee?
Every change is already committed and cannot roll back.
Try another answer. Uncommitted flushed changes can still be rolled back with the rest of the transaction.
Flush commits the row if the session is closed afterward.
Try another answer. Closing a session does not replace the explicit commit boundary.
SQL has been issued within the current transaction; commit is still required.
Correct. Flush exposes generated values and database errors without confirming durability.
This practice does not assess your project or award a certificate.
Your reading progress
Progress is saved in this browser when storage is available.