Как user.get_profile () может вернуть один набор данных, а user.account - другой? - PullRequest
1 голос
/ 16 марта 2012

Моя установка выглядит примерно так:

# account/models.py
Account(models.Model):
    """ The user profile """
    user = models.OneToOneField("auth.User", primary_key=True, related_name="account")
    balance = models.DecimalField(max_digits=32, decimal_places=2, default=0)
    activation_key = models.CharField(max_length=32)
    ...

И у меня есть обработчик сигнала, который выглядит следующим образом:

def recalculate_credit(sender, instance=None, created=None, **kwargs):

    print(instance.user.account.activation_key)

    account = instance.user.get_profile()

    print(account.activation_key)

    account.calculate_balance()
    account.save()

Я добавил операторы печати, чтобы подчеркнуть проблему. Во время процесса регистрации я установил свойство activation_key, сохранить, а затем этот сигнал срабатывает позже. Первый оператор print возвращает этот ключ активации, второй возвращает ''.

Как это возможно? Я что-то упускаю из-за того, как работает .get_profile()? Приведенный выше код фактически удаляет значение activation_key из учетной записи пользователя. Происходит ли ленивая загрузка или кеширование объектов, о которых я не знаю?

1 Ответ

3 голосов
/ 16 марта 2012

Да, так что здесь происходит то, что django не перезагружает атрибут .account attr или значение .get_profile() из БД каждый раз, он кэшируется после первого доступа. Чтобы исправить это, либо получите полностью свежую копию из БД с Account.objects.get(id=user.account_id), когда вам нужно гарантировать, что объект свежий, либо получите доступ к связанному Account объекту через либо API .get_profile(), либо .account связанный дескриптор - не оба. Если вы обращаетесь к объекту так же, как и до вызова .save(), у вас не должно быть этой проблемы.

Концептуально, основная проблема заключается в том, что Django не выполняет сопоставление идентичности - Foo.objects.get(id=1), если выполнить его дважды, приведет к двум отдельным Foo объектам в памяти. Их атрибуты не будут переданы, и обновление одного не изменит другого. Более уместно считать их «снимками» того, как выглядела строка БД этой модели, когда она была извлечена из БД. Чтобы выяснить, какое значение БД составляет , сейчас , вам нужно снова выполнить запрос.

...