web-dev-qa-db-fra.com

Django: L'objet WSGIRequest 'n'a pas d'attribut' utilisateur 'sur certaines pages?

Je souhaite créer un cookie si l'utilisateur est connecté ou non.

Mon 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

Ajouté à MIDDLEWARE_CLASSES dans settings.py à la fin.

Problème:

  • Erreur: l'objet 'WSGIRequest' n'a pas d'attribut 'utilisateur'
  • Pourquoi, alors que les middlewares d’authentification et de session sont déjà actifs?
  • En outre, certaines pages fonctionnent sans heurts, alors que d'autres donnent cette erreur.
  • Qu'est-ce que je fais mal ?

S'il vous plaît aider.

18
Yugal Jindle

Selon le FineManual:

Pendant les phases de réponse (middleware process_response () et process_exception ()), les classes sont appliquées dans l'ordre inverse, de bas en haut.

Je dirais donc que vous feriez mieux d'ajouter votre middleware avant les middlewares auth et session (en supposant qu'il ne traite que la réponse).

Ceci étant dit, je suis un peu perplexe de ne pas avoir d'erreur sur certaines pages ???

12

Récemment, nous avons rencontré le même problème et constaté que cela se produisait lorsqu'un utilisateur accédait à une URL sans le slash final, et que le paramètre APPEND_SLASH était défini sur true:


Django traite la demande initiale

  • CommonMiddleware.process_request
    • Redirige vers newurl, qui comporte le slash final
  • la réponse_processus est toujours exécutée dans le middleware personnalisé
    • request.user n'est pas présent
  • HTTP 301

Django traite ensuite la demande d'URL avec un slash final

  • process_response est exécuté dans un middleware personnalisé
    • request.user est maintenant présent

Tout le monde sait pourquoi certains des attributs principaux (utilisateur et session) ne sont pas accessibles dans process_response après une redirection permanente?

25
YacineAzmi

Cela concerne donc l'application de APPEND_SLASH avec une redirection par Django Common Middleware, ce qui empêche la process_request() dans AuthenticationMiddleware (qui ajoute l'attribut user) de s'exécuter, mais votre process_response toujours en cours d'exécution.

Voici comment fonctionne Django Process Middleware ACTUALLY (à partir de Django/core/handlers/base.py dans Django 1.6)

  1. Vous demandez une URL sans barre oblique. Alors yourdomain.com/view. Cela démarre le flux de middleware.
  2. Une fois que la demande atteint CommonMiddleware, le middleware voit qu'il n'y a pas de barre oblique et renvoie un http.HttpResponsePermanentRedirect(newurl). Ceci arrête immédiatement tout process_requests supplémentaire, y compris celui de AuthenticationMiddleware qui ajoute l'attribut user à request
  3. Étant donné que CommonMiddleware n'a pas renvoyé d'exception (y compris Http404), Django récupère maintenant la réponse du middleware et l'exécute via EVERY process_response() dans TOUS les middleware répertoriés dans MIDDLEWARE_CLASSES, que le process_request() de ce middleware ait eu la chance de s'exécuter.

Le seul moyen de résoudre ce problème consiste à déplacer votre code dans une méthode process_request() située après AuthenticationMiddleware dans MIDDLEWARE_CLASSES ou à détecter via hasattr() si l'objet request a un attribut user.

16
NickCatal

avez-vous actif ce middleware ?:

'Django.contrib.auth.middleware.AuthenticationMiddleware'

Et ce middleware s'exécute avant votre middleware?

9
Goin

J'ai eu un problème similaire, certaines de mes pages n'ont pas l'utilisateur dans la demande, donc dans mon middleware, je vérifie rapidement

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

Il se peut qu'une exception soit déclenchée dans un middleware ou dans tout autre code exécuté avant l'AuthenticationMiddleware de Django (responsable de l'affectation de l'objet .user à l'objet de requête).

Ensuite, il y aura une erreur AttributeError lors de l'accès à la variable .user.

Par exemple, toute exception déclenchée avant que AuthenticationMiddleware ait été exécutée peut entraîner l'exécution de la vue d'erreur. Vous obtiendrez l'erreur mentionnée dans le titre de la question, si la vue d'erreur dépend de request.user.

0
Evgeny