dbzero.atomic()
with dbzero.atomic() as atomic_context:
The atomic() method provides a context manager to group multiple database operations into a single, indivisible transaction. This ensures that all modifications within the with block are applied together, or none are applied at all. It's the standard way to guarantee data consistency when performing a sequence of related changes.
If the block completes successfully, all the changes are merged into the current transaction. If an exception occurs inside the block, or if the transaction is manually canceled, all changes are automatically rolled back, leaving your data in its original state.
Parameters
This method takes no parameters.
Yields
atomic_context(optional): An object that provides a single method,.cancel(), which you can call to programmatically discard all changes made within the current atomic block.
Side Effects
- Groups Mutations: Temporarily holds all data modifications (creations, updates, deletions) made within the
withblock. - Pauses Autocommit: Autocommit is suspended inside the atomic block to ensure the operations are treated as a single unit.
- Rolls Back on Failure: Automatically reverts all modifications if an unhandled exception is raised from within the block.
Examples
Grouping Successful Operations
Here, we create a new object and modify an existing one. Since the block exits without an error, both changes are applied.
obj1 = MyMemoClass("initial value")
with db0.atomic():
obj1.value = "updated value"
obj2 = MyMemoClass("new object")
db0.tags(obj2).add("new")
# Both changes are now visible
assert obj1.value == "updated value"
assert len(list(db0.find("new"))) == 1Automatic Rollback on Exception
If an error occurs, dbzero ensures that none of the changes from the failed block are saved.
obj = MyMemoClass(value=100)
try:
with db0.atomic():
obj.value = 200 # This change will be reverted
# A wild error appears!
raise ValueError("Something went wrong")
except ValueError:
print("Caught expected error.")
# The object's value is unchanged
assert obj.value == 100Manual Rollback with cancel()
You can also decide to discard changes based on your own application logic by calling atomic.cancel().
obj = MyMemoClass(value=100)
with db0.atomic() as atomic:
obj.value = 200
# Based on some condition, we decide to abort the transaction
if obj.value > 150:
print("Value too high, canceling.")
atomic.cancel()
# The changes were discarded
assert obj.value == 100An atomic() block does not immediately create a new, committed transaction or increment the global state number. Instead, its successful changes are staged and applied as part of the surrounding transaction, which is then committed either manually via dbzero.commit() or by the autocommit mechanism.