Django: WSGIRequest' object has no attribute 'user' on some pages?

30,251

Solution 1

According to the FineManual:

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

So I'd say you'd better add your middleware before the auth and session middlewares (assuming it only processes the response).

This being said, I'm a bit puzzled by the fact that you only have the error on some pages ???

Solution 2

Ran into the same issue recently, and found that it happened when a url is being accessed without the trailing slash, and the APPEND_SLASH setting is set to true:


Django processes initial request

  • CommonMiddleware.process_request
    • Redirects to newurl, which has the trailing slash
  • process_response is still run in custom middleware
    • request.user is not present
  • HTTP 301

Django then processes the request of url with trailing slash

  • process_response is run in custom middleware
    • request.user is now present

Anyone knows why some of the main attributes (user and session) are not accessible in process_response after a permanent redirect?

Solution 3

So it has to do with APPEND_SLASH being applied with via a redirect by Django Common Middleware, preventing the process_request() in AuthenticationMiddleware (which adds the user attribute) from being run but your process_response still being run.

Here's how Django Process Middleware ACTUALLY Works (from django/core/handlers/base.py in Django 1.6)

  1. You request a URL that does not have a trailing slash. So yourdomain.com/view. This starts the middleware flow.
  2. Once the request reaches CommonMiddleware, the middleware sees that there is not a slash and returns a http.HttpResponsePermanentRedirect(newurl). This immediately stops any additional process_requests from being run, including one in AuthenticationMiddleware that add the user attribute to request
  3. Because CommonMiddleware did not return an exception (including Http404), django will now take the response from the middleware and run it through EVERY process_response() in EVERY middleware listed in MIDDLEWARE_CLASSES, no matter if that middleware's process_request() had a chance to run.

The only real way to fix this is to either move your code into a process_request() method located after AuthenticationMiddleware in MIDDLEWARE_CLASSES or detect via hasattr() if the request object has a user attribute.

Solution 4

do you have active this middleware?:

'django.contrib.auth.middleware.AuthenticationMiddleware'

And this middleware run before your middleware?

Solution 5

I had a similar issue, some of my pages dont have the user in the request so in my middleware I do a quick check

if not hasattr(request, 'user'):
    return response
Share:
30,251
Yugal Jindle
Author by

Yugal Jindle

Everybody is a genius. But if you judge a fish by its ability to climb a tree, it will live its whole life believing that it is stupid. -- Anonymous Github : YugalJindle Twitter : @YugalJindle Google+ : +YugalJindle LinkedIn : http://www.linkedin.com/in/YugalJindle

Updated on July 05, 2022

Comments

  • Yugal Jindle
    Yugal Jindle almost 2 years

    I want to set a cookie if user is logged in or not.

    My 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
    

    Added to MIDDLEWARE_CLASSES in settings.py at the end.

    Problem:

    • Error: 'WSGIRequest' object has no attribute 'user'
    • Why, when I have the Authentication and the Session middlewares active already ?
    • Also, some pages are working smooth where as some are giving this error.
    • What am I doing wrong ?