В Django, как отправить пользователю сообщение после входа в систему? - PullRequest
1 голос
/ 19 января 2012

У меня есть сайт Django, на котором я показываю сообщение об успехе пользователю, когда он вошел в систему. Я делаю это с помощью сигнала, подобного этому:

def post_login_actions(sender, user, request, **kwargs):
    messages.success(request, "Hello There. You're now logged in.")

user_logged_in.connect(post_login_actions, dispatch_uid="user_logged_in")

Это все прекрасно работает на сайте,Но он выдает ошибки, когда я запускаю тесты для проверки возможности входа в систему.Вот мой тест:

def test_home_loggedin(self):
    c = Client()
    c.login(username='MYEMAIL', password='MYPASSWORD')
    response = c.get('/')
    self.assertEqual(response.status_code, 200)

(я понимаю, что в этом примере нет ничего, чтобы проверить, вошел ли пользователь в систему.) Вот результат:

Traceback (most recent call last):
  File "/Users/phil/Projects/RIG/projectname/django-projectname/projectname/tagger/tests/viewtests.py", line 34, in test_home_loggedin
    c.login(username='MYEMAIL', password='MYPASSWORD')
  File "/Users/phil/.virtualenvs/django-projectname/lib/python2.6/site-packages/django/test/client.py", line 516, in login
    login(request, user)
  File "/Users/phil/.virtualenvs/django-projectname/lib/python2.6/site-packages/django/contrib/auth/__init__.py", line 85, in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
  File "/Users/phil/.virtualenvs/django-projectname/lib/python2.6/site-packages/django/dispatch/dispatcher.py", line 172, in send
    response = receiver(signal=self, sender=sender, **named)
  File "/Users/phil/Projects/RIG/projectname/django-projectname/projectname/tagger/models/userprofile.py", line 234, in post_login_actions
    messages.success(request, "Hello There. You're now logged in.")
  File "/Users/phil/.virtualenvs/django-projectname/lib/python2.6/site-packages/django/contrib/messages/api.py", line 98, in success
    fail_silently=fail_silently)
  File "/Users/phil/.virtualenvs/django-projectname/lib/python2.6/site-packages/django/contrib/messages/api.py", line 26, in add_message
    raise MessageFailure('Without the django.contrib.messages '
MessageFailure: Without the django.contrib.messages middleware, messages can only be added to authenticated users.

(Вы могли заметить, что яЯ передаю адрес электронной почты в качестве имени пользователя. Это потому, что я делаю что-то по этим линиям , чтобы использовать адреса электронной почты вместо имен пользователей. Я не думаю, это частьпроблема ...)

Я не уверен, что проблема здесь.Если я закомментирую вызов messages.success, тогда тест выполняется нормально, и клиент успешно вошел в систему. Так почему он жалуется, что пользователь не аутентифицирован?

Ответы [ 2 ]

2 голосов
/ 19 января 2012

В обычных обстоятельствах AuthenticationMiddleware установит пользователя в качестве атрибута объекта запроса:

request.user = SimpleLazyObject(lambda: get_user(request))

Когда вы добавляете сообщение, Django сначала проверит, был ли установлен этот атрибут:

if hasattr(request, 'user') and request.user.is_authenticated():
    return request.user.message_set.create(message=message)

Но теперь вы запускаете тесты, и метод login для Client создает объект запроса с нуля без пользовательского атрибута.

Итак, выУ меня есть два варианта: установить патч Django или настроить приемник сигнала в этом случае, изменив его на следующее:

def post_login_actions(sender, user, request, **kwargs):
    if not hasattr(request, 'user'):
        setattr(request, 'user', user)
    messages.success(request, "Hello There. You're now logged in.")
0 голосов
/ 27 января 2013

Я рекомендую вместо хаков, упомянутых @roam, просто добавьте fail_silently=True аргумент к вызовам ваших сообщений - только к тем, которые нужно запускать в определенном месте, например, приемники сигналов (которые вы не хотите или можете перемещать) их на вид).

messages.info(request, "some message", fail_silently=True)

Это работает, поскольку не вызывает исключение MessageFailure. Компромисс из-за того, что это сообщение не показывается пользователю из-за какой-то другой ошибки, не так велик, когда мы рассматриваем отсутствие тестов для этого. И этот метод полностью поддерживается в django - это не какой-то хак, что ваш напарник по команде подумал бы «WTF»?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...