django-channels: differentiate between different `AnonymousUser`s

被刻印的时光 ゝ 提交于 2019-12-24 09:03:03

问题


Unfortunately I'm using django-channels channels 1.1.8, as I missed all the updates to channels 2.0. Upgrading now is unrealistic as we've just launched and this will take some time to figure out correctly.

Here's my problem:

I'm using the *message.user.id *to differentiate between authenticated users that I need to send messages to. However, there are cases where I'll need to send messages to un-authenticated users as well - and that message depends on an external API call. I have done this in ws_connect():

@channel_session_user_from_http
def ws_connect(message):
    # create group for user
    if str(message.user) == "AnonymousUser":
        user_group = "AnonymousUser" + str(uuid.uuid4())
    else:
        user_group = str(message.user.id)


    print(f"user group is {user_group}")
    Group(user_group).add(message.reply_channel)
    Group(user_group).send({"accept": True})
    message.channel_session['get_user'] = user_group

This is only the first part of the issue, basically I'm appending a random string to each AnonymousUser instance. But I can't find a way to access this string from the request object in a view, in order to determine who I am sending the message to.

Is this even achievable? Right now I'm not able to access anything set in the ws_connect in my view.

EDIT: Following kagronick's advice, I tried this:

@channel_session_user_from_http
def ws_connect(message):
    # create group for user

    if str(message.user) == "AnonymousUser":
        user_group = "AnonymousUser" + str(uuid.uuid4())
    else:
        user_group = str(message.user.id)

    Group(user_group).add(message.reply_channel)
    Group(user_group).send({"accept": True})
    message.channel_session['get_user'] = user_group
    message.http_session['get_user'] = user_group
    print(message.http_session['get_user'])
    message.http_session.save()

However, http_session is None when user is AnonymousUser. Other decorators didn't help.


回答1:


Yes you can save to the session and access it in the view. But you need to use the http_session and not the channel session. Use the @http_session decorator or @channel_and_http_session. You may need to call message.http_session.save() (I don't remember, I'm on Channels 2 now.). But after that you will be able to see the user's group in the view.

Also, using a group for this is kind of overkill. If the group will only ever have 1 user, put the reply_channel in the session and do something like Channel(request.session['reply_channel']).send() in the view. That way it doesn't need to look up the one user that is in the group and can send directly to the user.

If this solves your problem please mark it as accepted.




回答2:


EDIT: unfortunately this only works locally but not in production. when AnonymousUser, message.http_sesssion doesn't exist.

user kagronick got me on the right track, where he pointed that message has an http_session attribute. However, it seems http_session is always None in ws_connect when user is AnonymousUser, which defeats our purpose.

I've solved it by checking if the user is Anonymous in the view, and if he is, which means he doesn't have a session (or at least channels can't see it), initialize one, and assign the key get_user the value "AnonymousUser" + str(uuid.uuid4()) (this way previously done in the consumer).

After I did this, every time ws_connect is called message will have an http_session attribute: Either the user ID when one is logged in, or AnonymousUser-uuid.uuid4().



来源:https://stackoverflow.com/questions/51187309/django-channels-differentiate-between-different-anonymoususers

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