user.get_profile()如何返回一个数据集而user.account又一个?

时间:2012-03-16 10:44:46

标签: django user-profile

我的设置大致如下:

# 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 个答案:

答案 0 :(得分:3)

是的,所以这里发生的是django每次都不会从DB重新加载.account attr或.get_profile()的值,它在第一次访问后被缓存。要修复,当您需要保证对象是新鲜的,或者只通过 访问相关的Account.objects.get(id=user.account_id)对象时,要么使用Account从数据库获取一个全新的副本.get_profile() API或.account相关描述符 - 不是两者。只要您以与调用.save()之前相同的方式访问对象,就不会出现此问题。

从概念上讲,潜在的问题是Django没有进行任何身份映射 - Foo.objects.get(id=1),运行两次,会在内存中产生两个独立的Foo个对象。它们的属性不会被共享,更新一个不会改变另一个。将它们从数据库中恢复时,该模型的DB行看起来是什么样的“快照”更合适。要查明数据库值现在,您必须再次运行查询。