1👍
Looks like you’ll have to use raw SQL. I had a look through the current code and I think it would be more hassle to try and backport this yourself than it would be to just write the SQL.
account = AccountDetails.objects.raw(
"SELECT * FROM yourapp_accountdetails FOR UPDATE WHERE user = %s", [user.id]
)
For convenience and to keep your code DRY you can add this as a method to your AccountDetails model or something.
class AccountDetails(models.Model):
@classmethod
def get_locked_for_update(cls, user):
return cls.objects.raw(
"SELECT * FROM yourapp_accountdetails FOR UPDATE WHERE user = %s", [user.id]
)
yourapp
is the name of your application that you would have given when you ran startapp. I’m assuming you have a foreign key relationship on your AccountDetails to a user model of some kind.
The current implementation of select_for_update on Django 1.5 looks like this:
def select_for_update(self, **kwargs):
"""
Returns a new QuerySet instance that will select objects with a
FOR UPDATE lock.
"""
# Default to false for nowait
nowait = kwargs.pop('nowait', False)
obj = self._clone()
obj.query.select_for_update = True
obj.query.select_for_update_nowait = nowait
return obj
So that’s pretty simple code. Just setting a few flags on the query object. However those flags won’t mean anything when the query is executed. So at some point you’ll need to write raw SQL. At this point you only need that query on your AccountDetails model. So just put it there for now. Maybe later you’ll need it on another model. That’s when you’ll have to decide how to share the code between models.