Problema al conectar django y websockets flutter

programación


Estoy tratando de establecer una conexión con mi backend de Django y el código de Flutter usando WebSockets, pero desafortunadamente no puedo hacerlo, revisé muchos artículos y videos y todos básicamente hacen lo mismo sin recibir un error. Por favor, dé un Un pequeño empujón, soy un poco nuevo en esto.

Lo que he probado:

En primer lugar, creé una nueva aplicación de Django llamada ‘chat_app’ (la agregué a settings.py), donde creé un nuevo modelo de mis Mensajes:

Pitón
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

Luego hice mi consumer.py (aquí estoy un poco confundido, ¿no es mejor referirme a mi habitación Unique_id en lugar de nombre, ya que la identificación es única y no el nombre en mi caso? Decidí seguir con el tutorial.)

Pitón
# 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()

Hecho el enrutamiento.py

Pitón
# 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()),
    ]

Luego lo agregué a las URL de mi proyecto:

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

Y así es como intento establecer una conexión en Flutter, básicamente es una página nueva, donde paso datos de la habitación a través del Navegador desde la página anterior:

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

Salidas:

En la terminal de flutter recibo el siguiente mensaje:

[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

Donde “3wVCio” es el ID único de mi habitación.

Proporcionaré información adicional si es necesario.

Actualizar: Lo último que he probado es permitir todos los CORS de origen en mi proyecto:

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

Desafortunadamente, no hubo éxito.

Solución 1

Básicamente has respondido tu propia pregunta sin saberlo.

Cita:

Luego hice mi consumer.py (aquí estoy un poco confundido, ¿no es mejor referirme a mi habitación Unique_id en lugar de nombre, ya que la identificación es única y no el nombre en mi caso? Decidí seguir con el tutorial.)

Parece que estás usando ‘unique_id’ en Django, pero en Flutter, estás usando ‘roomName’. Asegúrese de utilizar los nombres de parámetros correctos en todos sus módulos. Actualice su Django ‘ChatConsumer’ para usar ‘room_name’ en lugar de ‘unique_id’ –

Pitón
self.unique_id = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.unique_id

Asegúrate de actualizar esto en todo tu código Django.

Luego, asegúrese de que la URL de WebSocket en su código Flutter esté usando el esquema correcto (‘ws o wss’) según la configuración de su servidor Django. Si su servidor Django usa ‘ws’, debe usar:

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

Sin embargo, si su servidor Django está configurado para WebSocket seguro (‘wss’), use –

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

Lo anterior debería resolver los errores.

コメント

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