2012-06-27 13 views
18

Ich möchte einen Cookie setzen, wenn der Benutzer eingeloggt ist oder nicht.Django: WSGIRequest 'Objekt hat auf einigen Seiten kein Attribut' Benutzer '?

Meine 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 

am Ende MIDDLEWARE_CLASSES in settings.py hinzugefügt.

Problem:

  • Fehler: 'WSGIRequest' Objekt hat kein Attribut 'user'
  • Warum, wenn ich die Authentifizierung und die Session aktiv Middle bereits?
  • Auch einige Seiten arbeiten reibungslos, wo einige diesen Fehler geben.
  • Was mache ich falsch?

Bitte helfen.

Antwort

12

der FineManual Nach:

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

Also sage ich Sie besser Ihre Middleware vor die Auth und Sitzungsmiddle hinzufügen würde (vorausgesetzt, es verarbeitet nur die Antwort).

Dies gesagt, ich bin ein wenig verwirrt, dass Sie nur den Fehler auf einigen Seiten haben ???

+4

Ich denke, dass einige Seiten nicht mit dem abschließenden Schrägstrich angehängt sind. – Babu

9

tun Sie diese Middleware ?:

'django.contrib.auth.middleware.AuthenticationMiddleware' 

Und diese Middleware laufen, bevor Sie Ihre Middleware aktiv haben?

22

lief in das gleiche Problem vor kurzem, und stellte fest, dass es passiert ist, wenn eine URL ohne den Schrägstrich zugegriffen wird, und die APPEND_SLASH Einstellung auf true gesetzt:


Django verarbeitet ursprüngliche Anforderung

  • CommonMiddleware.process_request
    • Umleitungen an newURL, die den Schrägstrich hat
  • process_response noch
    • Anfrage in kundenspezifische Middleware ausführen.Benutzer ist nicht vorhanden
  • HTTP 301

Django dann die Anforderung von URL-Prozesse mit Slash am Ende

  • process_response in benutzerdefinierten Middleware ausgeführt wird
    • request.user ist jetzt vorhanden

Jeder weiß, warum einige der wichtigsten Attribute (Benutzer- und Sitzungs) in process_response nach einer permanenten Umleitung nicht zugänglich sind?

+0

In Bezug auf warum: Es ist, weil CommonMiddleware einen 'HttpResponse'-Wert zurückgegeben hat, bevor' AuthenticationMiddleware.process_request' eine Chance hatte, ausgeführt zu werden, die 'AuthenticationMiddleware' vorgreift. "Wenn es ein HttpResponse-Objekt zurückgibt, wird Django keine anderen Anfragen, View- oder Exception-Middleware oder die entsprechende Ansicht aufrufen; es wird die Antwort-Middleware auf diese HttpResponse anwenden und das Ergebnis zurückgeben." -https: //docs.djangoproject.com/de/1.7/topics/http/middleware/#process-request –

13

So hat es damit zu tun, APPEND_SLASH mit von Django gemeinsame Middleware über eine Umleitung angewandt wird, verhindern, dass die process_request() in AuthenticationMiddleware (die die user Attribut fügt) an der Ausführung aber Ihr process_response noch das ausgeführt wird.

Hier ist, wie Django Prozessmiddleware tatsächlich funktioniert (von django/core/handlers/base.py in Django 1,6)

  1. Sie eine URL anfordern, die keinen Schrägstrich hat. Also yourdomain.com/view. Dies startet den Middleware-Fluss.
  2. Sobald die Anforderung CommonMiddleware erreicht, sieht die Middleware, dass es keinen Schrägstrich gibt und gibt eine http.HttpResponsePermanentRedirect(newurl) zurück. Dies stoppt sofort zusätzliche process_requests an der Ausführung, darunter eine in AuthenticationMiddleware, die das user Attribut request
  3. Da CommonMiddleware hinzufügen nicht eine Ausnahme zurückgeben (einschließlich Http404), wird django nehmen nun die Antwort von der Middleware und führen Sie es durch EVERY process_response() in jeder Middleware aufgeführt in MIDDLEWARE_CLASSES, egal ob diese Middleware process_request() eine Chance hatte zu laufen.

Die einzige wirkliche Möglichkeit, dies zu beheben, ist entweder, um Ihren Code in ein process_request() Verfahren nach AuthenticationMiddleware in MIDDLEWARE_CLASSES oder erfassen über hasattr() sich zu bewegen, wenn das request Objekt ein user Attribut hat.

+3

Das ist großartig! Meine App funktioniert, sobald ich die Middleware in dieser Reihenfolge eingerichtet habe: ('django.contrib.auth.middleware.AuthenticationMiddleware', 'MyMiddleware', 'django.middleware.common.CommonMiddleware') – Temuz

4

hatte ich ein ähnliches Problem, einige meiner Seiten in der Anforderung der Benutzer nicht haben so in meiner Middleware ich eine schnelle Überprüfung tun

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

Es könnte eine Ausnahme innerhalb einer Middleware oder einem anderen Code ausgelöst werden das vor der AuthenticationMiddleware des django läuft (die für die Zuweisung des .user zum request-Objekt verantwortlich ist).

Dann wird beim Zugriff auf die .user-Variable ein AttributeError angezeigt.

Zum Beispiel könnte jede Ausnahme, die ausgelöst wurde, bevor die AuthenticationMiddleware ausgeführt werden konnte, zur Ausführung der Fehleransicht führen. Sie erhalten den Fehler, wie im Titel der Frage erwähnt, wenn die Fehleransicht von request.user abhängt.