2010-06-09 6 views
16

Tengo el mismo enigma como presented in this question, pero aplicado al usuario de autenticación de Django.Cómo convertir request.user en una autenticación de proxy. Clase de usuario?

que tienen este modelo de poder:

class OrderedUser(User): 
    def __unicode__(self): 
     return self.get_full_name() 

    class Meta: 
     proxy=True 
     ordering=["first_name", "last_name"] 

Y algunos de mis otros modelos utilizan un OrderedUser en lugar de un django.contrib.auth.models.User como tipos de campo.

En mi punto de vista entonces utilice el request.user para poblar un campo y - como se esperaba - obtener un error:

'Cannot assign "<User...>": <field> must be a "OrderedUser" instance' 

tan sólo pudiera hacer OrderedUser.objects.get(request.user.id), pero eso es un golpe extra a la base de datos.

Entonces, ¿cómo convertir una clase de modelo base en su clase de proxy?

Respuesta

14

Es otro golpe de base de datos, pero esto va a funcionar:

OrderedUser.objects.get(pk=request.user.pk) 

Editar Usted podría intentar:

o = OrderedUser() 
o.__dict__ = request.user.__dict__ 
+0

derecho. ¿Hay algún mecanismo que no implique un golpe al DB? – cethegeek

+2

Sí, copiar el dict hizo el truco. Gracias Daniel. – cethegeek

+3

Gracias por este consejo. Sin embargo, una cosa que he encontrado es que al usar esto en un contexto_conceso para pasar un objeto de usuario a las plantillas ... debes hacerlo de manera diferente si el usuario no ha iniciado sesión. Como lo tienes, o siempre termina como un objeto OrderedUser (desciende del usuario), pero si el usuario no ha iniciado sesión, debe ser del tipo AnonymousUser. Entonces probaría si 'request.user.is_authenticated()' y si es así, solo entonces haz lo anterior. De lo contrario, haz 'o = request.user'. –

10

no pude conseguir el método de copia dict para trabajar en Python 2.7 .4 y Django 1.6. No tracé todo el camino hacia abajo, pero creo que tenía algo que ver con que era un objeto perezoso.

lo que funcionó para mí:

request.user.__class__ = OrderedUser 

Evita la llamada base de datos y da acceso a la materia de autenticación de base y todos mis comportamientos extendidos.

para que la ley request.user como la clase de proxy siempre, puso la asignación en el middleware después el middleware de autenticación y antes de cualquiera de mis aplicaciones podrían hacer referencia a ella. Como se llama al middleware en cada solicitud, asegúrese de que el usuario esté autenticado antes de configurar la clase. Usando su ejemplo, aquí es cómo el código de middleware puede tener un aspecto:

from yourapp.models import OrderedUser 

class OrderedUserMiddleware(): 
    def process_request(self, request): 
     if hasattr(request, 'user') and request.user.is_authenticated(): 
      request.user.__class__ = OrderedUser 

Y recuerde registrar el software intermedio después de la autenticación:

MIDDLEWARE_CLASSES = [ 
    # ...middleware from the guts of Django, none of your middle wares yet... 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    # ...more middleware from the guts of Django, none of your middlewares yet... 
    'yourapp.middleware.OrderedUserMiddleware', 
    # ...more middleware from you other middlewares... 
] 
+0

Justo lo que estoy buscando. – Charlesliam

+0

Esto funciona muy bien, excepto que no pude conseguir que el middleware funcionara con la autenticación django-rest-framework y tuve que recurrir a la configuración de __class__. – MrDBA

Cuestiones relacionadas