Problème lors de la connexion des websockets Django et Flutter

la programmation


J’essaie d’établir une connexion avec mon backend Django et mon code Flutter à l’aide de WebSockets, mais malheureusement je ne parviens pas à le faire, j’ai parcouru de nombreux articles et vidéos et tout le monde fait essentiellement la même chose sans recevoir d’erreur. Veuillez donner un petit coup de pouce, je suis un peu nouveau dans ce domaine.

Ce que j’ai essayé :

Tout d’abord, j’ai créé une nouvelle application Django appelée ‘chat_app’ (je l’ai ajoutée dans settings.py), où j’ai créé un nouveau modèle de mes messages :

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

Ensuite, j’ai créé mon consumer.py (ici, je suis un peu confus, n’est-il pas préférable de faire référence à ma chambre unique_id au lieu de son nom, puisque l’identifiant est unique et non le nom dans mon cas ? J’ai décidé de m’en tenir au Didacticiel.)

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()

Terminé le routage.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()),
    ]

Ensuite, je l’ai ajouté aux URL de mon projet :

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

Et c’est ainsi que j’essaie d’établir une connexion dans Flutter, en gros, c’est une nouvelle page, où je transmets les données de la pièce via le navigateur de la page précédente :

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);
      });
    });
  }

Les sorties:

Dans le terminal Flutter, j’obtiens le message suivant :

[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

Où le “3wVCio” est l’identifiant unique de ma chambre.

Je fournirai des informations supplémentaires si besoin

Mise à jour: La dernière chose que j’ai essayée consiste à autoriser tous les CORS d’origine dans mon projet :

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

Malheureusement, aucun succès..

Solution 1

En gros, vous avez répondu à votre propre question sans le savoir –

Citation:

Ensuite, j’ai créé mon consumer.py (ici, je suis un peu confus, n’est-il pas préférable de faire référence à ma chambre unique_id au lieu de son nom, puisque l’identifiant est unique et non le nom dans mon cas ? J’ai décidé de m’en tenir au Didacticiel.)

Il semble que vous utilisiez « unique_id » dans Django, mais dans Flutter, vous utilisez « roomName ». Assurez-vous que vous utilisez les noms de paramètres corrects dans tous vos modules. Mettez à jour votre Django ‘ChatConsumer’ pour utiliser ‘room_name’ au lieu de ‘unique_id’ –

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

Assurez-vous de mettre à jour cela dans tout votre code Django.

Assurez-vous ensuite que l’URL WebSocket dans votre code Flutter utilise le schéma correct (« ws ou wss ») en fonction de la configuration de votre serveur Django. Si votre serveur Django utilise ‘ws’, vous devez utiliser –

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

Cependant, si votre serveur Django est configuré pour WebSocket sécurisé (« wss »), utilisez –

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

Ce qui précède devrait résoudre les erreurs.

コメント

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