Использование внешних каналов consumers.py но функция у потребителей не срабатывает

#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 следовательно, веб-сайты будут подключаться и отключаться каждый раз при загрузке новой страницы. Во время тестирования я загружаю свою домашнюю страницу в одном браузере и захожу на сайт с помощью другого браузера (в другой учетной записи), при этом предыдущая вкладка браузера остается открытой. Почти уверен, что я упустил здесь что-то очень важное. Дайте мне знать, если что-нибудь обнаружите.