Django:检索用户模型时自动选择相关模型UserProfile

时间:2018-03-06 15:44:45

标签: python django django-models

在Django模板中显示{{ user }}时,默认行为是显示用户名,即user.username

我正在更改此设置以显示用户的姓名首字母,这些首字母存储在单独的(OneToOneFieldUserProfile模型中。

所以在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

1 个答案:

答案 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 }}时,将显示缩写。