真的很困惑这里发生了什么。我的课程定义如下:
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中一个有趣的设计决定导致了这个问题吗?
答案 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)
Python属性本身do not work,因为django的模型可以设置实例属性。也许这会产生影响。