2012-06-27 23 views
18

Quiero establecer una cookie si el usuario está conectado o no.Django: ¿El objeto WSGIRequest 'no tiene atributo' usuario 'en algunas páginas?

Mi Middleware:

class UserStatus(object): 
    def process_response(self,request,response): 
     user_status = 1 if request.user.is_authenticated() else 0 
     max_age = (20)*52*7*24*60*60 # 20 years (After expiry, cookie gets deleted) 
     response.set_cookie(user_status_cookie,user_status,max_age) 
     return response 

Añadido a MIDDLEWARE_CLASSES en settings.py al final.

Problema:

  • error: objeto 'WSGIRequest' no tiene atributo 'usuario'
  • Por qué, cuando tengo la autenticación y los middleware sesión activa ya?
  • Además, algunas páginas funcionan sin problemas, ya que algunas están dando este error.
  • ¿Qué estoy haciendo mal?

Por favor ayuda.

Respuesta

12

De acuerdo con la FineManual:

During the response phases (process_response() and process_exception() middleware), the classes are applied in reverse order, from the bottom up

así que yo diría que es mejor que agregue su middleware antes de la autenticación y el middleware de sesión (suponiendo que sólo procesa la respuesta).

Dicho esto, estoy un poco desconcertado por el hecho de que solo tiene el error en algunas páginas ???

+4

Supongo que algunas páginas no se añaden con la barra al final. – Babu

9

tiene usted activa este middleware ?:

'django.contrib.auth.middleware.AuthenticationMiddleware' 

Y este middleware carrera antes de su middleware?

22

se encontró con el mismo problema hace poco, y encontraron que sucedió cuando se accede a una URL sin la barra final, y el ajuste APPEND_SLASH se establece en true:


Django procesa la solicitud inicial

  • CommonMiddleware.process_request
    • redirige a NEWURL, que tiene la barra final
  • process_response todavía se ejecuta en el middleware de encargo solicitud
    • .usuario no está presente
  • HTTP 301

Django continuación, procesa la solicitud de URL con barra final

  • process_response se ejecuta en middleware de encargo
    • request.user es ahora presente

Cualquiera sabe por qué algunos de los atributos principales (usuario y sesión) no son accesibles en process_response después de una redirección permanente?

+0

En cuanto a por qué: Se debe a que CommonMiddleware devolvió un valor 'HttpResponse' antes de que' AuthenticationMiddleware.process_request' tuviera la oportunidad de ejecutarse, lo que previene 'AuthenticationMiddleware'. "Si devuelve un objeto HttpResponse, Django no se molestará en llamar a ninguna otra solicitud, vista o excepción de middleware, o la vista apropiada, sino que aplicará el middleware de respuesta a esa HttpResponse y devolverá el resultado". -https: //docs.djangoproject.com/en/1.7/topics/http/middleware/#process-request –

13

por lo que tiene que ver con APPEND_SLASH que se aplica a través de una redirección por Django Común Middleware, la prevención de la process_request() en AuthenticationMiddleware (que añade el atributo user) que se ejecuten pero su process_response todavía se está ejecutando.

Así es como Proceso de Django Middleware realmente funciona (de django/core/handlers/base.py en Django 1,6)

  1. Se solicita una dirección URL que no tiene una barra final. Entonces yourdomain.com/view. Esto inicia el flujo de middleware.
  2. Una vez que la solicitud llega a CommonMiddleware, el middleware ve que no hay una barra inclinada y devuelve http.HttpResponsePermanentRedirect(newurl). Esto detiene inmediatamente cualquier process_requests adicional que se ejecuten, incluyendo uno en AuthenticationMiddleware que añadir el atributo user a request
  3. Debido CommonMiddleware no arrojó una excepción (incluyendo Http404), django tomará ahora la respuesta del middleware y ejecutarlo a través de cada process_response() en CUALQUIER middleware enumerado en MIDDLEWARE_CLASSES, sin importar si el middleware process_request() tuvo la oportunidad de ejecutarse.

La única manera de solucionar este problema es ya sea mover su código en un método process_request() localizado después AuthenticationMiddleware en MIDDLEWARE_CLASSES o detectar a través de hasattr() si el objeto tiene un atributo requestuser.

+3

¡Esto es genial! Mi aplicación funcionó una vez que coloqué el middleware en este orden: ('django.contrib.auth.middleware.AuthenticationMiddleware', 'MyMiddleware', 'django.middleware.common.CommonMiddleware') – Temuz

4

tuve un problema similar, algunos de mis páginas no tiene el usuario en la solicitud así que en mi middleware hago una comprobación rápida

if not hasattr(request, 'user'): 
    return response 
0

podría haber una excepción lanzada dentro de algún middleware o cualquier otro código que se ejecuta antes del AuthenticationMiddleware de django (que es responsable de asignar el .user al objeto request).

Luego habrá un AttributeError al acceder a la variable .user.

Por ejemplo, cualquier excepción activada antes de que AuthenticationMiddleware tuviera la oportunidad de ejecutarse podría ocasionar la ejecución de la vista de error. Obtendrá el error mencionado en el título de la pregunta, si la vista de error depende de request.user.

Cuestiones relacionadas