مشكلة عند توصيل مآخذ الويب Django وflutter


أحاول إنشاء اتصال مع واجهة Django الخلفية وكود Flutter باستخدام WebSockets، لكن لسوء الحظ لم أتمكن من القيام بذلك، لقد قمت بمراجعة العديد من المقالات ومقاطع الفيديو والجميع يفعل الشيء نفسه دون تلقي خطأ.. من فضلك قم بإعطاء دفعة صغيرة، أنا جديد نوعا ما في هذا.

ما حاولت:

أولاً، قمت بإنشاء تطبيق Django جديد يسمى “chat_app” (أضفته إلى settings.py)، حيث أنشأت نموذجًا جديدًا لرسائلي:

بايثون
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 (هنا أنا في حيرة من أمري، أليس من الأفضل الإشارة إلى معرف غرفتي الفريد بدلاً من الاسم، نظرًا لأن المعرف فريد وليس الاسم في حالتي؟ قررت الالتزام بـ درس تعليمي.)

بايثون
# 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

بايثون
# 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 لمشروعي:

بايثون
urlpatterns = [
        path('admin/', admin.site.urls),
        ...,
        path('ws/', include(websocket_urlpatterns)),
    ]

وهذه هي الطريقة التي أحاول بها إنشاء اتصال في Flutter، وهي في الأساس صفحة جديدة، حيث أقوم بتمرير بيانات الغرفة من خلال Navigator من الصفحة السابقة:

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” هو المعرف الفريد لغرفتي.

سأقدم معلومات إضافية إذا لزم الأمر

تحديث: آخر ما قمت بتجربته هو السماح بجميع CORS الأصلية في مشروعي:

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

للأسف لا يوجد نجاح..

الحل 1

لقد أجبت بشكل أساسي على سؤالك دون أن تعرف ذلك –

يقتبس:

ثم قمت بإنشاء Consumers.py (هنا أنا في حيرة من أمري، أليس من الأفضل الإشارة إلى معرف غرفتي الفريد بدلاً من الاسم، نظرًا لأن المعرف فريد وليس الاسم في حالتي؟ قررت الالتزام بـ درس تعليمي.)

يبدو أنك تستخدم “unique_id” في Django، ولكن في Flutter، فأنت تستخدم “roomName”. تأكد من أنك تستخدم أسماء المعلمات الصحيحة خلال الوحدات النمطية الخاصة بك. قم بتحديث Django “ChatConsumer” الخاص بك لاستخدام “room_name” بدلاً من “unique_id” –

بايثون
self.unique_id = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.unique_id

تأكد من تحديث هذا في كل كود Django الخاص بك.

ثم تأكد من أن عنوان URL لـ WebSocket في كود Flutter الخاص بك يستخدم المخطط الصحيح (“ws أو wss”) بناءً على تكوين خادم Django الخاص بك. إذا كان خادم 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をコピーしました