Opened 9 years ago
Closed 9 years ago
#25271 closed Bug (invalid)
model object locking with select_related
Reported by: | Vathsala Achar | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.8 |
Severity: | Normal | Keywords: | models, select_related, resource locking |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I used select_related (django 1.6 on windows connected to sqlserver) and came across some unexpected behaviour.
Here's an example that I tested with django 1.8 and sqlite:
class TestUser(models.Model): name = models.CharField(blank=True, max_length=255) class Account(models.Model): user = models.OneToOneField(TestUser) name = models.CharField(max_length=255) value = models.IntegerField(default=0)
I tried the following code against the models above to replicate the unexpected behaviour I noticed.
def some_method(some_id): t = TestUser.objects.select_related('account').get(id=some_id) # here is where the fun stuff happens alter_account(t.id) # the following changes are reflected in the db t.account.name= 'something else' t.account.save() def alter_account(uid): ''' this method does not work as expected as the select_related in the previous method has locked the Account model out ''' a = Account.objects.get(user__id=uid) a.value = 5 a.save() test_user = TestUser.objects.create(name='test user') test_account = Account.objects.create(user=test_user, name='some account')
Initial state:
>>> test_account.name u'some account' >>> test_account.value 0
Expected:
>>> test_account.name u'something else' >>> test_account.value 5
Unexpected result:
>>> some_method(test_user.id) >>> test_account.name u'something else' >>> test_account.value 0
I found this in our production code when the object state refused to update and caused us issues. I had to get rid of the select_related in the query to resolve the issue.
Nowhere in the documentation is this behaviour explained, so I assume this is a bug.
This is expected behavior because
select_related()
has already fetch the related accounts. Since you modify a separate model instance, the originally fetched instance becomes stale.