Model Locks
pglock.model is a wrapper around Postgres's LOCK statement and can be used to lock an entire model.
Basic Usage
pglock.model must be used in a transaction. Once called, the lock will be held for the duration of the transaction. For example:
from django.db import transaction
import pglock
with transaction.atomic():
pglock.model("auth.User")
Tip
pglock.model can be called with model paths or model classes. Supply multiple models to lock more than one, for example, pglock.model("auth.User", "auth.Group")
.
Above we've locked Django's auth user table. By default, it's locked in access exclusive mode. In other words, no other processes can read or modify the table. Below we've locked the user table in access share mode:
See the Postgres docs for a breakdown of all lock levels and how they conflict with one another. django-pglock
has corresponding constants for each mode.
Warning
When using nested transactions, the lock will be held until either the inner one is rolled back or the outermost call completes. To ensure your transactions aren't nested, use transaction.atomic(durable=True)
.
Configuring Lock Wait Time
By default, pglock.model will wait forever until the lock can be acquired. Use the timeout
argument to change this behavior.
For example, timeout=0
will avoid waiting for the lock:
with transaction.atomic():
acquired = pglock.model("auth.User", timeout=0)
if acquired:
# The lock is acquired
As shown above, the acquisition status is returned to indicate if the lock was successfully acquired. Here we wait up to two seconds to acquire the lock:
Tip
Use a datetime.timedelta
argument for timeout
for better precision or None
to set an infinite timeout.
Side Effects
The side_effect
argument adjusts runtime characteristics when using a timeout. For example, below we're using timeout=0
and side_effect=pglock.Raise
to raise an exception if the lock cannot be acquired: