Django: объект WSGIRequest 'не имеет атрибута' пользователь 'на некоторых страницах?

Я хочу установить cookie, если пользователь вошел в систему или нет.

Мое промежуточное ПО:

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

Добавлен в MIDDLEWARE_CLASSES в settings.py в конце.

Проблема:

  • Ошибка: объект WSGIRequest не имеет атрибута user
  • Почему, когда у меня уже есть промежуточное ПО для аутентификации и сеанса?
  • Кроме того, некоторые страницы работают плавно, а некоторые выдают эту ошибку.
  • Что я делаю неправильно ?

person Yugal Jindle    schedule 27.06.2012    source источник


Ответы (6)


Согласно FineManual:

На этапах ответа (промежуточное ПО process_response () и process_exception ()) классы применяются в обратном порядке, снизу вверх.

Поэтому я бы сказал, что вам лучше добавить свое промежуточное программное обеспечение до промежуточного программного обеспечения аутентификации и сеанса (при условии, что оно обрабатывает только ответ).

При этом я немного озадачен тем фактом, что у вас есть ошибка только на некоторых страницах ???

person bruno desthuilliers    schedule 27.06.2012
comment
Я предполагаю, что некоторые страницы не добавлены с косой чертой. - person Babu; 13.03.2013

Недавно столкнулся с той же проблемой и обнаружил, что это происходит, когда доступ к URL-адресу осуществляется без завершающей косой черты, а для параметра APPEND_SLASH установлено значение true:


Django обрабатывает первоначальный запрос

  • 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 обрабатывает запрос URL-адреса с завершающей косой чертой

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

Кто-нибудь знает, почему некоторые из основных атрибутов (пользователь и сеанс) недоступны в process_response после постоянного перенаправления?

person YacineAzmi    schedule 10.02.2013
comment
Относительно того, почему: это потому, что CommonMiddleware вернул значение HttpResponse до того, как AuthenticationMiddleware.process_request успел запуститься, что вытесняет AuthenticationMiddleware. Если он возвращает объект HttpResponse, Django не будет беспокоиться о вызове какого-либо другого промежуточного программного обеспечения для запросов, представлений или исключений или соответствующего представления; он применит промежуточное ПО для ответа к этому HttpResponse и вернет результат. - https://docs.djangoproject.com/en/1.7/topics/http/middleware/#process-request - person CJ Gaconnet; 16.10.2014

Таким образом, это связано с тем, что APPEND_SLASH применяется с помощью перенаправления Django Common Middleware, предотвращая запуск process_request() в AuthenticationMiddleware (который добавляет атрибут user), но ваш process_response все еще выполняется.

Вот как ДЕЙСТВИТЕЛЬНО работает промежуточное ПО процесса Django (из django/core/handlers/base.py в Django 1.6)

  1. Вы запрашиваете URL без косой черты. Итак yourdomain.com/view. Это запускает поток промежуточного программного обеспечения.
  2. Когда запрос достигает CommonMiddleware, промежуточное ПО видит, что косой черты нет, и возвращает http.HttpResponsePermanentRedirect(newurl). Это немедленно останавливает выполнение любых дополнительных process_requests, в том числе тех из AuthenticationMiddleware, которые добавляют атрибут user к request
  3. Поскольку CommonMiddleware не вернул исключение (включая Http404), django теперь будет принимать ответ от промежуточного программного обеспечения и запускать его через КАЖДУЮ process_response() в КАЖДОМ промежуточном программном обеспечении, указанном в MIDDLEWARE_CLASSES, независимо от того, была ли process_request() этого промежуточного программного обеспечения возможность работать.

Единственный реальный способ исправить это - либо переместить ваш код в метод process_request(), расположенный после AuthenticationMiddleware в MIDDLEWARE_CLASSES, или определить с помощью hasattr(), имеет ли объект request атрибут user.

person NickCatal    schedule 13.01.2014
comment
Отлично! Мое приложение заработало, когда я разместил промежуточное ПО в следующем порядке: ('django.contrib.auth.middleware.AuthenticationMiddleware', 'MyMiddleware', 'django.middleware.common.CommonMiddleware') - person Temuz; 05.03.2014

у вас есть активное это промежуточное ПО ?:

'django.contrib.auth.middleware.AuthenticationMiddleware'

И это промежуточное ПО запускается перед вашим промежуточным ПО?

person Goin    schedule 27.06.2012

У меня была аналогичная проблема, на некоторых моих страницах нет пользователя в запросе, поэтому в моем промежуточном программном обеспечении я быстро проверяю

if not hasattr(request, 'user'):
    return response
person sidarcy    schedule 10.02.2014

Может возникнуть исключение в некотором промежуточном программном обеспечении или любом другом коде, который выполняется до AuthenticationMiddleware django (который отвечает за назначение .user объекту запроса).

Тогда при доступе к переменной .user будет AttributeError.

Например, любое исключение, инициированное до запуска AuthenticationMiddleware, может вызвать выполнение представления ошибок. Вы получите сообщение об ошибке, указанное в заголовке вопроса, если представление ошибки зависит от request.user.

person Evgeny    schedule 22.11.2015