2011-06-29 7 views
9

¿Cómo puedo usar un administrador personalizado para la clase auth_user en django?Anular UserManager en django

En mi proyecto django, estoy usando auth_user y tengo una clase de perfil básica. En cada página de mi sitio, utilizo algunos datos de usuario y perfil, por lo que cada consulta de usuario debe unirse al perfil.

Quería usar select_related en el método get_query_set() en un administrador personalizado, pero no puedo encontrar una forma adecuada de definir uno, o anular el UserManager existente. ¿Algunas ideas?

Nota: No quiero anular el modelo de usuario. O, para ser más precisos, ya lo superé en diferentes modelos proxy. Quiero que este administrador personalizado se use en todos los modelos de proxy.

Respuesta

6

Ok, finalmente encontró la respuesta correcta. La forma más limpia es utilizar un back-end de autenticación personalizado.

# 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 
3

Esto es bastante feo, pero probablemente se pueda parchar la propiedad de usuario objects, por ejemplo. en un middleware:

# 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 

luego vuelva a colocar la línea en settings.py:

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

Por:

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

Nota 1: este código es puramente teórico, no probado ni tengo tiempo para hacerlo.

Nota2: No podría recomendar el uso de esta solución desde un punto de vista de mantenimiento a largo plazo.

Nota 3: Si alguien sugiere algo más, probablemente debería escucharlo más que a mí.

Nota 4: Como una idea probablemente mejor, ¿por qué no intentas consultar Perfil, que es una clase de modelo sobre la que tienes control total? Siempre puede recuperar el objeto de usuario de un perfil de todos modos, así que ...

+0

Como no puedo encontrar ninguna manera más limpia, voy a aceptar esta respuesta. Sin embargo, he llenado un informe de error en el django BT. Espera y verás. https://code.djangoproject.com/ticket/16379 –

+3

Realmente no debería aceptar esta respuesta, porque los principiantes podrían concluir que es un enfoque aceptable para resolver el problema que plantea, mientras que no lo es. – NiKo

+0

Intenté y no funcionó, por desgracia ... Hubiera sido una solución simple para mí – James

Cuestiones relacionadas