连接 django 和 flutter websockets 时出现问题

编程


我正在尝试使用 WebSockets 与我的 Django 后端和 Flutter 代码建立连接,但不幸的是我无法这样做,浏览了很多文章和视频,每个人基本上都在做同样的事情而没有收到错误。有点推动,我对此有点陌生。

我尝试过的:

首先,我创建了一个名为“chat_app”的新 django 应用程序(将其添加到 settings.py 中),在其中创建了消息的新模型:

Python
class Message(models.Model):
        room = models.ForeignKey(Room, on_delete=models.CASCADE)
        sender = models.ForeignKey(User, on_delete=models.CASCADE)
        content = models.TextField()
        timestamp = models.DateTimeField(auto_now_add=True)
    
        def __str__(self):
            return self.content

然后我制作了consumers.py(在这里我有点困惑,引用我的房间unique_id而不是名称不是更好吗,因为ID是唯一的,而不是我的情况下的名称?决定坚持使用教程。)

Python
# chat/consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async
from .models import Message
from room_app.models import Room

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.unique_id = self.scope['url_route']['kwargs']['unique_id']
        self.room_group_name = 'chat_%s' % self.unique_id

        # Check if the room exists in the database
        if not await self.room_exists():
            await self.close()
            return

        # Join room group
        self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        self.accept()

    def disconnect(self, close_code):
        # Leave room group
        self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        # Save message to database
        Message.objects.create(
            room=self.unique_id,
            user=self.scope['user'],
            content=message
        )

        # Send message to room group
        self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message,
                'username': self.scope['user'].username
            }
        )

    # Receive message from room group
    def chat_message(self, event):
        message = event['message']
        username = event['username']

        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'message': message,
            'username': username
        }))
    
    @sync_to_async
    def room_exists(self):
        return Room.objects.filter(unique_id=self.unique_id).exists()

完成路由.py

Python
# The WebSocket URL pattern for chat rooms is defined by this code
    websocket_urlpatterns = [
        re_path(r'ws/chat_app/(?P<room_name>\w+)/$', ChatConsumer.as_asgi()),
    ]

然后将其添加到我的项目 URL 中:

Python
urlpatterns = [
        path('admin/', admin.site.urls),
        ...,
        path('ws/', include(websocket_urlpatterns)),
    ]

这就是我尝试在 Flutter 中建立连接的方式,基本上它是一个新页面,我在其中通过上一页的导航器传递房间数据:

class ChatScreen extends StatefulWidget {
  const ChatScreen({
    Key? key,
    required this.room,
  }) : super(key: key);
  final RoomModelResponse room;

  @override
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final TextEditingController _controller = TextEditingController();
  final List<String> _messages = [];
  late WebSocketChannel _channel;

  @override
  void initState() {
    super.initState();
    _channel = IOWebSocketChannel.connect(
        'wss://192.168.0.11:8000/ws/chat_app/${widget.room.roomName}/'); // Update the WebSocket URL with your Django server address and room name
    _channel.stream.listen((message) {
      setState(() {
        _messages.add(message);
      });
    });
  }

输出:

在颤振终端中,我收到以下消息:

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: WebSocketChannelException: WebSocketChannelException: WebSocketException: Connection to 'http://192.168.0.11:8000/ws/chat_app/3wVCio/#' was not upgraded to websocket
#0      new IOWebSocketChannel._withoutSocket.<anonymous closure> (package:web_socket_channel/io.dart:119:24)
#1      Stream.handleError.<anonymous closure> (dart:async/stream.dart:931:16)
#2      _HandleErrorStream._handleError (dart:async/stream_pipe.dart:269:17)
#3      _ForwardingStreamSubscription._handleError (dart:async/stream_pipe.dart:157:13)
#4      _RootZone.runBinaryGuarded (dart:async/zone.dart:1606:10)
#5      _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358:15)
#6      _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:376:7)
#7      _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:280:7)
#8      _SyncStreamControllerDispatch._sendError (dart:async/stream_controller.dart:788:19)
#9 <…>

姜戈:

Not Found: /ws/chat_app/3wVCio/
[15/Feb/2024 16:46:19] "GET /ws/chat_app/3wVCio/ HTTP/1.1" 404 4379

其中“3wVCio”是我房间的 unique_id。

如果需要,我会提供更多信息

更新: 我最近尝试过的想法是允许我的项目中的所有原始 CORS:

INSTALLED_APPS = [
    # other installed apps
    'corsheaders',
]
CORS_ALLOW_ALL_ORIGINS = True

不幸的是,没有成功。。

解决方案1

你基本上已经在不知情的情况下回答了你自己的问题 –

引用:

然后我制作了consumers.py(在这里我有点困惑,引用我的房间unique_id而不是名称不是更好吗,因为ID是唯一的,而不是我的情况下的名称?决定坚持使用教程。)

您似乎在 Django 中使用“unique_id”,但在 Flutter 中,您使用“roomName”。 确保您在整个模块中使用正确的参数名称。 更新您的 Django ‘ChatConsumer’ 以使用 ‘room_name’ 而不是 ‘unique_id’ –

Python
self.unique_id = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.unique_id

确保在所有 Django 代码中更新此内容。

然后确保 Flutter 代码中的 WebSocket URL 使用基于 Django 服务器配置的正确方案(“ws 或 wss”)。 如果您的 Django 服务器使用“ws”,您应该使用 –

_channel = IOWebSocketChannel.connect(
    'ws://192.168.0.11:8000/ws/chat_app/${widget.room.roomName}/');

但是,如果您的 Django 服务器配置为安全 WebSocket (‘wss’),请使用 –

_channel = IOWebSocketChannel.connect(
    'wss://192.168.0.11:8000/ws/chat_app/${widget.room.roomName}/');

以上应该可以解决错误。

コメント

タイトルとURLをコピーしました