【问题标题】:Override UserManager in django在 Django 中覆盖 UserManager
【发布时间】:2011-09-24 23:40:36
【问题描述】:

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

在我的 django 项目中,我使用的是auth_user,并且我有一个基本的配置文件类。在我网站的每个页面中,我都会使用一些用户和个人资料数据,因此每个用户查询都应该加入个人资料。

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

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

【问题讨论】:

    标签: django authentication usermanager


    【解决方案1】:

    好的,终于找到正确答案了。最简洁的方法是使用自定义身份验证后端。

    # 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
    

    【讨论】:

      【解决方案2】:

      这是相当丑陋的,但你可能可以猴子补丁 User 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 中填写了错误报告。等着瞧。 code.djangoproject.com/ticket/16379
      • 你真的不应该接受这个答案,因为初学者可能会得出结论,这是解决你提出的问题的一种可接受的方法,而事实并非如此。
      • 试过了,可惜没用...对我来说是一个简单的解决方法
      猜你喜欢
      • 2014-01-29
      • 2011-09-21
      • 2019-01-01
      • 2020-10-07
      • 2014-08-15
      • 1970-01-01
      • 2017-08-23
      • 2020-11-08
      • 2011-11-13
      相关资源
      最近更新 更多