#django-channels
Вопрос:
Я пытаюсь отправить сообщение джанго consumers.py от одного пользователя к другому после входа пользователя в систему. Однако функция chat_message, похоже, не работает с кодом, который я написал в функции входа в систему в views.py как «ccc» при отсутствии печати на стороне сервера. Новичок в каналах Django здесь. Был бы признателен за любой вклад в решение этой моей проблемы.
consumers.py
class OnlineFriends(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope["user"]
print(self.room_name)
print(self.channel_layer)
self.room_group_name = 'chat_' str(self.room_name)
print(self.room_group_name)
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
print("aa")
message = self.channel_name.split("-")
await self.send(text_data=json.dumps({
'message': message
}))
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
async def chat_message(self, event):
print("ccc")
message = event['message']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message
}))
users.views.py *Обновлено
class Login(View):
form_class = LoginForm
template = 'login.html'
def get(self, request):
form=self.form_class(None)
return render(request, self.template, {'form':form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password")
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
user.onlinestatus = True
user.save()
for obj in user.friends.all():
print( user.friends.all())
if obj.onlinestatus == True:
print("obj: " str(obj.username))
channel_layer = get_channel_layer()
print("channel_layer: " str(channel_layer))
room_name = "chat_" str(obj.username)
print("room_name: " str(room_name))
print(obj.channel_name)
async_to_sync(channel_layer.group_send(
room_name, {
"type": "chat.message",
"message": room_name,
}))
return redirect('home')
else:
return HttpResponse("No such user.")
else:
return render(request, 'login.html', {'form':form})
обновлена обратная связь
WebSocket HANDSHAKING /friendslist/ [127.0.0.1:49751] ****loading home page on browser****
foonghanyao ****output from consumers.OnlineFriends.connect****
RedisChannelLayer(hosts=[{'address': ('127.0.0.1', 6379)}])
chat_foonghanyao
WebSocket CONNECT /friendslist/ [127.0.0.1:49751]
HTTP GET /static/songs/images/favicon.png 200 [0.02, 127.0.0.1:61225]
<QuerySet [<User: foonghanyao>]> ****output from Login class in views.py****
obj: foonghanyao
channel_layer: RedisChannelLayer(hosts=[{'address': ('127.0.0.1', 6379)}])
room_name: chat_foonghanyao
specific.45d45ec67e0a4282b2066d67847e4bab!8ab6617c8be94d0dabefadf636ba886e
HTTP POST /accounts/login/ 302 [0.88, 127.0.0.1:60752]
<QuerySet [<Tag: apple>, <Tag: bee>]>
HTTP GET /home/ 200 [0.16, 127.0.0.1:60752]
WebSocket DISCONNECT /friendslist/ [127.0.0.1:55762] ****Disconnecting from websockets in login page****
aa
WebSocket HANDSHAKING /friendslist/ [127.0.0.1:58978] ****new page loading after being redirected following log in****
brandonfoong
RedisChannelLayer(hosts=[{'address': ('127.0.0.1', 6379)}])
chat_brandonfoong
WebSocket CONNECT /friendslist/ [127.0.0.1:58978]
sync.routing.py обновлено
websocket_urlpatterns = [
re_path(r"^friendslist/$", consumers.OnlineFriends.as_asgi(), name='friendslist'),
]
mainapp.asgi.py обновлено
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "music.settings")
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
sync.routing.websocket_urlpatterns,
)
),
})
Комментарии:
1. Можете ли вы объяснить, каков ваш желаемый результат и что вы получаете, во-первых, при использовании канального уровня вы также должны передать объект, который вы получаете
<asgiref.sync.AsyncToSync object at 0x00000207C8311B38>
в данный момент, потому что вы печатаете ссылку на объект в консоль. Таким образом, используйтеself.channel_layer.group_send
.2. Я пытаюсь заставить пользователей отправлять сообщение при входе в систему другим связанным пользователям, которые уже вошли в систему. Прямо сейчас я хочу, чтобы моя функция входа в views.py чтобы запустить chat_message в consumers.py. Раз уж вы заговорили об этом, могу я узнать, в чем разница между self.channel_layer.group_send и channel_layer.group_send? Это просто channel_layer.group_send в документации, где он учит отправлять сообщения за пределы consumers.py. Я получаю «объект’Login’ не имеет атрибута ‘channel_layer'», делая то, что вы предложили, используя CBV здесь.
3. Я думаю, что ты делаешь что-то не так. Я скопировал ваш код, и он работает на меня. Я переоделся только
self.room_name = self.scope["user"]
для того, чтобыself.room_name = self.scope["user"].username
. Я не совсем понимаю, что вы делаете в своей views.py ноasync_to_sync(channel_layer.group_send(channel_name,{"type":'chat_message',"message": channel_name, }))
меня это устраивает. Вы уверены, что во время отправки сообщения группе к ней был подключен пользовательroom_group_name
?4. Насколько я понимаю, вы хотите уведомить одного пользователя о том, что другой пользователь только что вошел в систему. Вам необходимо убедиться, что пользователь, которого вы хотите уведомить, подключен к WebSocket и что вы отправляете сообщение в его комнату, а не в комнату пользователя, который только что вошел в систему.
5. Я добавил некоторую дополнительную информацию в свой ответ на вопрос. Мой вывод остается прежним, функция chat.message в комсомольцах не запускается. Просто в довершение того, что я делаю, я построил свой сайт таким образом, что написал свой код websockets в base.html следовательно, веб-сайты будут подключаться и отключаться каждый раз при загрузке новой страницы. Во время тестирования я загружаю свою домашнюю страницу в одном браузере и захожу на сайт с помощью другого браузера (в другой учетной записи), при этом предыдущая вкладка браузера остается открытой. Почти уверен, что я упустил здесь что-то очень важное. Дайте мне знать, если что-нибудь обнаружите.