Python属性:两个变量实例?

时间:2010-02-08 00:33:55

标签: python django

真的很困惑这里发生了什么。我的课程定义如下:

class Profile(models.Model):
    user = models.OneToOneField(User)
    primary_phone = models.CharField(max_length=20)
    address = models.ForeignKey(Address)

    @property
    def primary_email(self): return self.user.email
    @primary_email.setter
    def primary_email(self, val): self.user.email = val

注意:user有一个属性email

现在从命令行开始,我正在尝试这个:

>>> u = User.objects.get(pk=1)
>>> u.email = 'xxx'
>>> u.profile.primary_email
u'yyy'

它会吐出不同的价值吗?具体来说,u.email值。这是怎么回事?这怎么可能?我基本上只想为email创建一个别名。


更多信息:

>>> id(u) == id(u.profile.user)
False
>>> u
<User: mark>
>>> u.profile.user
<User: mark>

它们似乎是user的不同副本,但它们......什么?两者都以相同的值开始?

这样做似乎提交了更改:

>>> u.profile.primary_email = 'yyy'
>>> u.profile.user.save()

但是u.save()无法做到这一点,因为u != u.profile.user无论出于什么原因。我想这可以回答我的问题,但它仍然有些蹩脚。

可能这两个人在Python中引用同一个对象,对吗?这只是Django中一个有趣的设计决定导致了这个问题吗?

2 个答案:

答案 0 :(得分:2)

我不是Django用户,但我猜是因为你在更改u.email后没有更新模型。在通过个人资料访问用户的电子邮件之前,请尝试调用u.save()(或任何恰好调用的方法)。

您可以使用Django的signaling功能来构建变通方法。基本上,在Profile.user发送post_save时更新User

# models.py
...
def update_user(**kwargs):
    kwargs['instance'].profile.user = kwargs['instance']

models.signals.post_save.connect(update_user, sender=User)

您仍然需要致电User.save才能使此工作正常,而且Profile.user可能会产生其他副作用。可能有更多的Django-y方式;有更多Django经验的人比我发布的还要多。例如,可以挂钩在您第一次访问User.profile时调用的代码并将Profile.user设置为父用户,而不是创建新的User

或者,只要您通过Users.objects.get获得用户并引用Users.profile,请使用User.profile中的用户属性替换用户对象。

答案 1 :(得分:2)

django模型中的

Python属性本身do not work,因为django的模型可以设置实例属性。也许这会产生影响。