Problem when connecting Django and Flutter websockets
I'm trying to establish a connection with my Django backend and Flutter code using WebSockets, but unfortunately I'm unable to do so, went through many articles and videos and everyone is basically doing the same without receiving an error.. Please give a little push to, I'm kinda new into this.
First of all I created a new django app called 'chat_app' (added it into settings.py), where I created a new model of my Messages:
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
Then I made my consumers.py (here I'm a little bit confused, isn't it better to refer to my room unique_id instead of name, since the ID is unique and not the name in my case? Decided to stick with the tutorial.)
class ChatConsumer(WebsocketConsumer):
def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# 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
)
Done the routing.py
# 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()),
]
Then added it into my project URLs:
urlpatterns = [
path('admin/', admin.site.urls),
...,
path('ws/', include(websocket_urlpatterns)),
]
And this is how I'm trying to establish a connection in Flutter, basically it is a new page, where I'm passing room data through the Navigator from the previous page:
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://http://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);
});
});
}
Outputs:
In the flutter terminal I get the following 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 <…>
Django:
Not Found: /ws/chat_app/3wVCio/
[15/Feb/2024 16:46:19] "GET /ws/chat_app/3wVCio/ HTTP/1.1" 404 4379
Where the "3wVCio" is the unique_id of my room.
I will provide additional information if need
in your ChatScreen file there is URL which is quite unusual because there suppose to be only one protocol either wss or http but you are using both so that might be the issue.
if you want to use web socket then protocol suppose to be only wss or ws.
What helped me:
- I have installed redis using
brew-brew install redis - I have started redis, before starting my Django project -
redis-serverI'm not redis expert, please refer to official redis website - I have installed
daphnepip install daphneand added it into myINSTALLED_APPSin settings.py:
# Application definition
INSTALLED_APPS = [
'daphne',
...,
]
- I have added
ASGI_APPLICATIONinsettings.pyand configured myasgi.py. Insettings.py:
ASGI_APPLICATION = 'project.asgi.application'
- In
asgi.py:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns
),
)
})
- I have added
CHANNEL_LAYERSlike so insettings.py:
# Configure channel layers
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [('localhost', 6379)],
},
},
'ROUTING': 'ws.routing.application',
}
And with that, I have finally managed to connect "HANDSHAKE" and "CONNECT" with the WebSocket. I'm sorry, that I cannot give explanation why all of these worked. I just wanted to show, what worked for me.
WebSocket HANDSHAKING /ws/chat_app/FxmZiA/ [192.168.0.11:60081]
WebSocket CONNECT /ws/chat_app/FxmZiA/ [192.168.0.11:60081]