Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django locking between clean() and save()

Tags:

python

django

Let's say I have a model with a unique field email:

class MyModel:

    email = models.EmailField(unique=True)

    def save(self):
        .... # save model

    def clean(self):
        .... # validate model, make sure email doesn't already exist.

Usually if a browser submits a form with email being a value that already exists, it would raise a ValidationError, due to the model form field validation.

If two browsers submits the same email at the same time, with email being a value that doesn't exist yet, at least one of the requests will succeed by saving a row into the database. The other request, if it arrives long enough after the first one, will be treated normally - with a ValidationError raised saying the email already exists. But if it arrives almost at the same time as the first one, then the clean() will succeed - the email doesn't exist yet, but by the time the save() method is executed, the row from the first request would have been saved. In this latter case, a IntegrityError will be raised instead and the server would return an Internal Server 500 error, which is undesirable.

How can this last scenario be prevented? Database transactions?

like image 720
Eric Avatar asked Aug 28 '13 08:08

Eric


2 Answers

Just to use Django database transactions in this case will not be enough. What you want to do when creating a new model is to use database table lock together with transaction. But Django has no API for locking tables yet, therefore you will have to use raw SQL to perform a table lock for your database regarding of its type.

If you use PostgreSQL, here is a perfect example: http://www.caktusgroup.com/blog/2009/05/26/explicit-table-locking-with-postgresql-and-django/

If you are under some other db, you will have to investigate how to perform table lock.

like image 151
Simanas Avatar answered Oct 02 '22 16:10

Simanas


While the use case is slightly different, you might want to read this old answer from Alex Martelli about "optimistic concurrency" approach.

like image 33
Germano Avatar answered Oct 02 '22 14:10

Germano