在Django模板中显示{{ user }}
时,默认行为是显示用户名,即user.username
。
我正在更改此设置以显示用户的姓名首字母,这些首字母存储在单独的(OneToOneField
)UserProfile
模型中。
所以在customsignup/models.py
我已成功覆盖__unicode__
函数,并获得了所需的结果:
# __unicode__-function overridden.
def show_userprofile_initials(self):
return self.userprofile.initials
User.__unicode__ = show_userprofile_initials
但是,当然,数据库再次被击中,因为每次要求UserProfile
对象将其自身显示为字符串时,它需要独立选择user
模型。因此即使这样可行,它也会使数据库命中数增加很多。
所以我想做的是,每当从数据库调用select_related('userprofile')
模型时自动使用User
,看到我在处理用户时基本上总是需要配置文件第一名。
在更多技术术语中,我试图覆盖现有模型的模型管理器。所以我无法控制User
模型定义本身,因为那是在导入的库中。
所以我尝试覆盖objects
模型的User
成员,就像我覆盖__unicode__
函数一样,如下所示:
# A model manager for automatically selecting the related userprofile-table
# when selecting from user-table.
class UserManager(models.Manager):
def get_queryset(self):
# Testing indicates that code here will NOT run.
return super(UserManager, self).get_queryset().select_related('userprofile')
User.objects = UserManager()
这应该有效吗?如果是这样,我错了什么?
(我会将答案标记为正确,如果它可以证明这不应该首先起作用。)
我发现的类似问题就在这里,但是从另一端接近: Automatically select related for OneToOne field
答案 0 :(得分:1)
不,User.objects = MyManger()
不应该起作用。 According to the docs,只有两种支持的方法可以扩展提供的auth用户模型,可以是 profile 模型,也可以是代理模型,可能不适合你的情况。从文档(强调添加):
有两种方法可以扩展默认用户模型而无需替换您自己的模型。如果您需要的更改纯粹的行为,并且不需要对数据库中存储的内容进行任何更改,则可以基于用户创建代理模型。这允许代理模型提供的任何功能,包括默认排序,自定义管理器或自定义模型方法。
如果您希望存储与用户相关的信息,可以将OneToOneField用于包含其他信息字段的模型。这种一对一模式通常称为个人资料模型,因为它可能存储有关网站用户的非身份验证相关信息。
作为扩展提供的auth用户模型的替代方法,您可以provide your own custom User model。然后,您将完全控制其经理。
相反,请考虑将{{ user }}
替换为{{ user.profile.initials }}
。在配置文件模型上创建OneToOne字段还会为相关模型的实例创建反向访问器。您可以通过配置文件模型字段上的related_name关键字参数指定反向访问者名称。例如......
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model)
user = models.OneToOneField('auth.User', related_name='profile')
initials = models.CharField(max_length=6)
some_user = User.objects.first()
# assuming there is already a profile related to this user
some_user.profile.initials = 'S.P.Y.'
您还可以为您的个人资料模型制作__str__
方法,例如
def __str__(self):
return self.initials
然后,当您在模板中执行{{ user.profile }}
时,将显示缩写。