Подключение приложения flutter к django с помощью веб-сокетов
Я совсем новичок в WebSockets, так что в основном я пытаюсь сделать все возможное, чтобы создать в моем проекте Django и интегрировать его в мой проект Flutter. Идея состоит в том, чтобы иметь комнаты и участников этих комнат, чтобы иметь возможность общаться. Итак, в настройках Django я добавил 'daphne'
в установленных приложениях я создал потребителей чата следующим образом:
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
# scope is the request parameters passed from the url route
self.room_id = self.scope['url_route']['kwargs']['room_id']
self.room_group_name = 'chat_%s' % self.room_id
# 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):
# Leave room
await self.channel_layer.group_discard(self.room_group_name, self.channel_name)
Вот как выглядит моя комната и модели сообщений:
class Message(models.Model):
"""Chat message model"""
body = models.TextField()
sent_by = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
class Meta:
ordering = ('created_at',)
def __str__(self):
return f'{self.sent_by}'
class Room(models.Model):
class Meta:
verbose_name_plural = "Rooms"
unique_id = models.CharField(
max_length=8,
primary_key=True,
editable=False,
unique=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=101, null=True, blank=True)
password = models.CharField(max_length=50, blank=True, null=True)
users = models.ManyToManyField(User, through='UserRoom', related_name='users_room')
messages = models.ManyToManyField(Message, blank=True)
def __str__(self) -> str:
return str(self.name)
Я добавил потребителей к своим урлам:
path('ws/<str:room_id>', chat_consumers.ChatConsumer.as_asgi()),
И настроил мой asgi.py следующим образом:
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.settings')
from my_app import urls
# Gets the application we are currently in
django_asgi_application = get_asgi_application()
# Configure asgi application, setting up the ProtocolRouter
application = ProtocolTypeRouter(
{
'http': django_asgi_application,
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(URLRouter(urls.urlpatterns))
)
}
)
Хватит с django.
В моем приложении Flutter я создал новый класс с функцией для подключения к каналу websocket, используя пакет web_socket_channel
:
class WSChannel {
final _baseURL = "here is the URL, which I run django server on, 192.168.0.1:8000, just example URL";
final String roomID;
WSChannel({required this.roomID});
connectToChannel() {
final channel =
WebSocketChannel.connect(Uri.parse('wss://$_baseURL/$roomID'));
return channel;
}
}
Сейчас я в основном следую учебнику, предоставленному Flutter, для связи с WebSocket. В моем экранном виджете я пытаюсь подключиться к WebSocket:
@override
Widget build(BuildContext context) {
final channel = WSChannel(roomID: widget.room.uniqueID).connectToChannel();
return Scaffold(
backgroundColor: bluePrimary,
body: SafeArea(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 36, vertical: 16),
child: Column(children: [
Form(
child: TextFormField(
controller: _controller,
decoration:
const InputDecoration(labelText: 'Send a message'),
),
),
const SizedBox(height: 24),
StreamBuilder(
stream: channel.stream,
builder: (context, snapshot) {
return Text(snapshot.hasData ? '${snapshot.data}' : '');
},
),
FloatingActionButton(
onPressed: () {
if (_controller.text.isNotEmpty) {
channel.sink.add(_controller.text);
}
},
tooltip: 'Send message',
child: const Icon(Icons.send),
)
]))),
);
}
Затем я вижу следующий вывод:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: HandshakeException: Connection terminated during handshake
ОБНОВИТЬ:
После выполнения этого решения мне удалось получить связь с моим сервером django. Однако она отклоняется. Вот моя новая ошибка во flutter:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: WebSocketException: Connection to 'http://192.168.0.1:8000/sjfAmH#' was not upgraded to websocket
#0 _WebSocketImpl.connect (dart:_http/websocket_impl.dart:1011:41)
#1 WebSocket.connect (dart:_http/websocket.dart:320:22)
#2 new IOWebSocketChannel.connect (package:web_socket_channel/io.dart:81:28)
#3 WSChannel.connectToChannel (package:watch_with_me/webSockets/websocket_channel.dart:11:28)
#4 _InsideRoomPageState.build (package:watch_with_me/pages/room/inside_room_page.dart:20:61)
#5 StatefulElement.build (package:flutter/src/widgets/framework.dart:5583:27)
#6 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5471:15)
#7 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#8 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#9 StatefulElement.update (package:flutter/src/widgets/framework.dart:5657:5)
#10 <…>
А в консоли django:
WebSocket HANDSHAKING /sjfAmH [192.168.0.1:57255]
WebSocket REJECT /sjfAmH [192.168.0.1:57255]
WebSocket DISCONNECT /sjfAmH [192.168.0.1:57255]