Adam Starrh
Adam Starrh

Reputation: 6958

Django Channels: Saving logged in user to session

According to the docs:

If you are in a WebSocket consumer, or logging-in after the first response has been sent in a http consumer, the session is populated but will not be saved automatically - you must call scope["session"].save() after login in your consumer code:

However, I am having some trouble implementing this.

I start by getting my user:

def login(form_data):
    try:
        user = User.objects.get(username=form_data['username'])
    except User.DoesNotExist:
        return "This account doesn't exist."
    password = form_data['password']
    if check_password(password, user.password):
        return user
    else:
        return "Incorrect Password."

And then following the directions like so:

user = login(form_data)
async_to_sync(login)(self.scope, user)
self.scope["session"].save()
self.send(text_data=to_json({
    'operation': 'set_user',
    'success': True,
    'message': "Loading User Data",
    'object': {'username': user.username}
}))

And it works to deliver the user to the page and set it up for the life of the consumer. However, it seems that the user is not being saved to the user's session, because when I reload the page, self.scope['user'] once again returns an AnonymousUser object.

This is how I've got my asgi.py set up:

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            routing.websocket_urlpatterns
        )
    ),
})

Likewise, navigating to other pages confirms that I am indeed not logged in. What could I be missing?

Upvotes: 2

Views: 698

Answers (1)

Brian Destura
Brian Destura

Reputation: 12068

It looks like your login function is conflicting with channels.auth.login. Changing its name should fix it:

from channels.auth import login

def my_login(form_data):
    try:
        user = User.objects.get(username=form_data['username'])
    except User.DoesNotExist:
        return "This account doesn't exist."
    password = form_data['password']
    if check_password(password, user.password):
        return user
    else:
        return "Incorrect Password."

user = my_login(form_data)
async_to_sync(login)(self.scope, user)
self.scope["session"].save()
self.send(text_data=to_json({
    'operation': 'set_user',
    'success': True,
    'message': "Loading User Data",
    'object': {'username': user.username}
}))

Also the strings that are returned from my_login should be exceptions raised, right?

Upvotes: 1

Related Questions