【问题标题】:Python properties: Two instances of variable?Python 属性:变量的两个实例?
【发布时间】:2010-02-08 00:33:55
【问题描述】:

真的对这里发生的事情感到困惑。我有一个类定义如下:

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.emailold 值。这是怎么回事?这怎么可能?我基本上只是想为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 中一个有趣的设计决定造成的吗?

【问题讨论】:

  • 创建 User.profile 的代码在哪里? id(u) == id(u.profile.user)?
  • @outis:在那儿:user = models.OneToOneField(User)。 Django 就是这么神奇。

标签: python django


【解决方案1】:

python 属性本身 do not work 在 django 模型中,因为 django 的模型在设置实例属性方面做了一些魔术。也许这正在产生影响。

【讨论】:

    【解决方案2】:

    我不是 Django 用户,但我猜这是因为您在更改 u.email 后没有更新模型。在通过配置文件访问用户的电子邮件之前,请尝试调用 u.save()(或任何碰巧调用的方法)。

    您可以使用 Django 的 signaling 功能来构建解决方法。基本上,当User 发送post_save 时更新Profile.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 的用户属性。

    【讨论】:

    • 你猜对了,它是u.save(),但这不起作用。无论如何,打印u.email 而不保存将打印“xxx”。我认为使用属性,它会引用完全相同的实例变量?
    • u.profile.user 很可能是指围绕 DB 对象的包装器; id(u) == id(u.profile.user) 会告诉您更多信息,以及检查各种对象的属性。
    • 哦。我不知道这个id 函数。你是对的,它们是不同的。
    • 不错的编辑。那可以工作......无论如何,这实际上只是一个便利属性。这不是什么大不了的事。希望它保持一致,以便电话和电子邮件属性都出现在个人资料上,而不是一个在这里,一个在那里。
    猜你喜欢
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    相关资源
    最近更新 更多