Reputation: 2524
I'm concerned about one thing.
Using Django 1.7 (MySQL in the most default installation) I'm making a POST to a Django REST Framework APIView
.
Over there I'm doing a:
try:
MyModel.objects.get(**some_kwargs)
except MyModel.DoesNotExist:
MyModel.objects.custom_create(**some_kwargs) # This also creates relative models
Now what will happen if I'll do plenty of concurrent requests?
As I guess you expect I want only the first concurrent request to create an object and any other should get the created one.
Am I ready to go thanks do Django? Have to study about isolation, transactions, atomicity? Or is it more about locking the table? How to (unit) test it?
Please guide me.
Upvotes: 4
Views: 2490
Reputation: 53719
This is not enough to avoid race conditions, as another request can create the model you intended to retrieve between get()
and custom_create()
. If uniqueness is enforced on a database level, your custom_create()
method can fail with an IntegrityError
. If it is not, your method is fine, but you cannot prevent duplicate entries due to race conditions.
Django provides the get_or_create()
function. This safeguards against race conditions if uniqueness is enforced by your database. It uses the create()
method, however, not your custom_create()
method, so you'll have to override it if it is acceptable. Otherwise, you can checkout out the source code for get_or_create()
and implement it yourself with your custom create method.
The core assumption of get_or_create
is that uniqueness is enforced on a database level. Due to this enforcement, create
fails if a race condition occurs, and get_or_create
can fall back to fetching the object created during the race condition. If this enforcement is missing, the create
doesn't fail during a race condition, and a duplicate entry (with a different PK) will be created.
Upvotes: 8