Reputation: 12638
I'm running into an issue accessing a changed model field, traversing relationships in a Django 1.3 app. Changes committed to the database are not being reflected by in-memory objects. I'm using the User() object from Auth Middleware, linking it to a custom Profile() object:
User() <---one-to-one---> Profile()
The issue comes up when accessing the email
field for a User():
$ python manage.py shell
>>> from django.contrib.auth.models import User
>>> from myproject.myapp.models import Profile
>>>
>>> user = User.objects.get(pk=1)
>>> profile = user.profile
>>> user.email
u'[email protected]' # OK.
>>> profile.user.email
u'[email protected]' # OK.
>>>
>>> user.email = '[email protected]' # 1) Changes email address.
>>> user.save() # 2) Commits to database.
>>> user.email
'[email protected]' # 3) Changes reflected in user.email. Good.
>>> profile.user.email
u'[email protected]' # 4) Wrong. This is the old incorrect email.
>>> user.profile.user.email
u'[email protected]' # 5) Also wrong.
>>>
>>> profile = Profile.objects.get(user=user)
>>> profile.user.email
u'[email protected]' # 6) If we re-query the DB, things are OK.
Why do things get out of sync in steps #4 and #5? I'm baffled by #5, going from the saved user object, to the profile, and back to the same saved user object.
Obviously there is some sort of caching going on, but I'm not sure of the logic/algorithm behind it. Anyone have an idea of what's happening, and the best way to approach this in code? Thanks for any insight you can offer! :)
Upvotes: 2
Views: 672
Reputation: 62813
The SingleRelatedObjectDescriptor
descriptor responsible for transparently looking up the related object checks for a cached version of the related object in _<fieldname>_cache
in the Model instance, caching it the first time it is retrieved.
Django's ORM doesn't use an identity map, so changes to one Model instance aren't automatically reflected in other instances which existing references are held to.
Upvotes: 4
Reputation: 799170
profile.user
is not user
. What you are looking at is another cached copy of the model that Django's ORM had previously pulled from the database. If you absolutely must have the latest value then you will need to requery each time.
Upvotes: 2