Почему поля модели Django не синхронизируются при обходе отношений? - PullRequest
0 голосов
/ 26 апреля 2011

Я сталкиваюсь с проблемой доступа к измененному полю модели, перебирая отношения в приложении Django 1.3. Изменения, внесенные в базу данных, не отражаются объектами в памяти. Я использую объект User () из Auth Middleware, связываю его с пользовательским объектом Profile ():

User() <---one-to-one---> Profile()

Проблема возникает при доступе к полю email для пользователя ():

$ 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'old@example.com'                  # OK.
>>> profile.user.email
u'old@example.com'                  # OK.
>>> 
>>> user.email = 'new@example.com'  # 1) Changes email address.
>>> user.save()                     # 2) Commits to database.
>>> user.email
'new@example.com'                   # 3) Changes reflected in user.email. Good.
>>> profile.user.email
u'old@example.com'                  # 4) Wrong. This is the old incorrect email.
>>> user.profile.user.email
u'old@example.com'                  # 5) Also wrong.
>>> 
>>> profile = Profile.objects.get(user=user)
>>> profile.user.email
u'new@example.com'                  # 6) If we re-query the DB, things are OK.

Почему вещи не синхронизируются на шагах № 4 и № 5? Я сбит с толку # 5, переходя от сохраненного пользовательского объекта к профилю и обратно к тому же сохраненному пользовательскому объекту.

Очевидно, что происходит какое-то кэширование, но я не уверен в логике / алгоритме. Кто-нибудь имеет представление о том, что происходит, и лучший способ приблизиться к этому в коде? Спасибо за любые идеи, которые вы можете предложить! :)

Ответы [ 2 ]

2 голосов
/ 26 апреля 2011

Дескриптор SingleRelatedObjectDescriptor, отвечающий за прозрачный поиск связанных объектов, проверяет кэшированную версию связанного объекта в _<fieldname>_cache в экземпляре модели, кэшируя его при первом получении.

ORM в Django не использует карту идентичности, поэтому изменения в одном экземпляре модели не отражаются автоматически в других экземплярах, на которые имеются существующие ссылки.

1 голос
/ 26 апреля 2011

profile.user - это , а не user.То, на что вы смотрите, - это еще одна кэшированная копия модели, которую ORM Джанго ранее извлек из базы данных.Если вам абсолютно необходимо иметь последнее значение, вам придется каждый раз запрашивать.

...