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.

Change History (1)

comment:1 by Tim Graham, 9 years ago

Resolution: invalid
Status: newclosed

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.

Note: See TracTickets for help on using tickets.
Back to Top