问题
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