In Django, how to send a post-login message to the user?

丶灬走出姿态 提交于 2019-12-31 04:15:07

问题


I have a Django site in which I show a success message to the user when they've logged in. I do this with a signal like this:

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")

That all works fine on the site. But it throws errors when I run tests to test the login facility. Here's my test:

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

(I realise there's nothing in that example to test whether the user is logged in.) Here's the result:

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.

(You may have noticed I'm passing an email address as the username. This is because I'm doing something along these lines to use email addresses instead of usernames. I don't think this is part of the problem...)

I'm not sure what the problem is here. If I comment out the messages.success call then the test runs fine and the Client has successfully logged in. So why does it complain that the user isn't authenticated?


回答1:


In normal circumstances, the AuthenticationMiddleware will set the user as an attribute on the request object:

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

When you add a message, Django will first check whether that attribute has been set:

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

But now you're running tests and the login method of Client creates a request object from scratch without the user attribute.

So you've got two options: patching Django or making your signal receiver work in this case by changing it to this:

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.")



回答2:


I recommend instead of hacks mentioned by @roam, just add fail_silently=True argument to your messages calls - just to those ones that need to be run in the specific place like signals listeners (which you don't want or can move them to a view).

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

This works as it does not raise MessageFailure exception. The tradeoff of not having this message displayed to user due to some other kind of error is not so big when we consider not having tests for that. And this method is fully supported in django - it is not any kind of hack that your teammate developer would think "WTF"?



来源:https://stackoverflow.com/questions/8930090/in-django-how-to-send-a-post-login-message-to-the-user

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!