在 Django 中覆盖 UserManager

10

如何在Django中为auth_user类使用自定义管理器?

在我的Django项目中,我正在使用auth_user,并拥有一个基本的profile类。在网站的每个页面上,我都使用了一些用户和profile数据,因此每个用户查询都应该加入profile。

我想在自定义管理器的get_query_set()方法中使用select_related,但我找不到任何定义一个合适的管理器或重写现有的UserManager的正确方式。有什么好的想法吗?

注意:我不想覆盖用户模型,更准确地说,我已经在不同的代理模型中进行了覆盖。我希望这个自定义管理器能在每个代理模型中使用。

2个回答

8

好的,最终找到了正确的答案。最干净的方法是使用自定义认证后端。

# in settings:
AUTHENTICATION_BACKENDS = ('accounts.backends.AuthenticationBackend',)


# in accounts/backends.py:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User


class AuthenticationBackend(ModelBackend):
    def get_user(self, user_id):
        try:
            # This is where the magic happens
            return User.objects. \
                select_related('profile'). \
                get(pk=user_id)
        except User.DoesNotExist:
            return None

4

这个方法比较丑陋,但是你可以尝试对用户的objects属性进行猴子补丁,例如在中间件中:

# manager.py
from django.contrib.auth.models import UserManager

class MyUserManager(UserManager):
    def get_query_set(self):
        qs = super(MyUserManager, self).get_query_set()
        return qs.select_related('profile')

# middleware.py
from django.contrib.auth.middleware import AuthenticationMiddleware
from managers import MyUserManager

class MyAuthMiddleware(AuthenticationMiddleware):
    def process_request(self, request):
        super(AuthenticationMiddleware, self).process_request(request)
        User.objects = MyUserManager()
        return None

然后在settings.py中替换该行:

MIDDLEWARE_CLASSES = (
    # ...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # ...
)

通过:

# settings.py
MIDDLEWARE_CLASSES = (
    # ...
    'yourapp.middleware.MyAuthMiddleware',
    # ...
)

注意1:此代码纯属理论,从未经过测试,我也没有时间测试。
注意2:从长期可维护性的角度来看,我无法推荐使用这个解决方案。
注意3:如果有人建议其他解决方案,你应该更多地听取他或她的意见而不是我。
注意4:作为一个可能更好的想法,为什么不尝试查询Profile,这是一个您完全控制的模型类?您总是可以从配置文件中检索用户对象,所以...

由于我找不到更好的方法,我将接受这个答案。但是,我已经在Django BT中填写了一个错误报告。等待观察。https://code.djangoproject.com/ticket/16379 - Thibault J
3
请不要接受这个答案,因为初学者可能会得出这是解决你提出的问题的可接受方法的结论,但事实并非如此。 - NiKo
尝试过了,但不幸的是没有成功...这对我来说本来是一个简单的解决方法。 - James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接