diff --git a/apps/chats/admin.py b/apps/chats/admin.py index bab8255..d7237c3 100644 --- a/apps/chats/admin.py +++ b/apps/chats/admin.py @@ -1,8 +1,4 @@ from django.contrib import admin +from apps.chats.models import Message -# Register your models here. - -from apps.chats.models import Chat, Message - -admin.site.register(Chat) admin.site.register(Message) diff --git a/apps/chats/consumers.py b/apps/chats/consumers.py index c13cef4..070682a 100644 --- a/apps/chats/consumers.py +++ b/apps/chats/consumers.py @@ -1,74 +1,32 @@ -import json +# consumers.py from channels.generic.websocket import AsyncWebsocketConsumer -from channels.db import database_sync_to_async -from django.contrib.auth.models import User -from .models import Message, Chat +import json class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): - # Extract chat_id from URL route self.chat_id = self.scope["url_route"]["kwargs"]["chat_id"] self.room_group_name = f"chat_{self.chat_id}" - # Ensure channel_layer is available - if self.channel_layer is None: - await self.close() - return - - # Join room group await self.channel_layer.group_add(self.room_group_name, self.channel_name) - await self.accept() - # Notify users about the new connection - await self.channel_layer.group_send( - self.room_group_name, {"type": "user_status", "status": "Online"} - ) + await self.accept() async def disconnect(self, close_code): - # Leave room group - if self.channel_layer is None: - return - await self.channel_layer.group_discard(self.room_group_name, self.channel_name) - # Notify users about the disconnection - await self.channel_layer.group_send( - self.room_group_name, {"type": "user_status", "status": "Offline"} - ) - async def receive(self, text_data): - # Process incoming message text_data_json = json.loads(text_data) - message = text_data_json.get("message", "") - user_id = text_data_json.get("user_id") - - # Retrieve chat and user - chat = await database_sync_to_async(Chat.objects.get)(id=self.chat_id) - user = await database_sync_to_async(User.objects.get)(id=user_id) + message = text_data_json["message"] + user = self.scope["user"].username - # Save the message to the database - await database_sync_to_async(Message.objects.create)( - chat=chat, user=user, content=message - ) - - # Broadcast the message to the chat group await self.channel_layer.group_send( self.room_group_name, - {"type": "chat_message", "message": message, "user": user.username}, + {"type": "chat_message", "message": message, "user": user}, ) async def chat_message(self, event): - # Handle incoming message message = event["message"] user = event["user"] - # Send message to WebSocket await self.send(text_data=json.dumps({"message": message, "user": user})) - - async def user_status(self, event): - # Handle user status update - status = event["status"] - - # Send status update to WebSocket - await self.send(text_data=json.dumps({"status": status})) diff --git a/apps/chats/models.py b/apps/chats/models.py index 47cd563..9f0a2c8 100644 --- a/apps/chats/models.py +++ b/apps/chats/models.py @@ -14,8 +14,8 @@ def __str__(self): class Message(BaseModel): - chat = models.ForeignKey(Chat, on_delete=models.CASCADE, related_name="messages") user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="messages") + chat = models.ForeignKey(Chat, on_delete=models.CASCADE, related_name="messages") text = models.TextField() def __str__(self): diff --git a/apps/chats/routing.py b/apps/chats/routing.py index f2bb90c..b2447f5 100644 --- a/apps/chats/routing.py +++ b/apps/chats/routing.py @@ -1,6 +1,7 @@ -from django.urls import path +# routing.py +from django.urls import re_path from . import consumers websocket_urlpatterns = [ - path("ws/chat//", consumers.ChatConsumer.as_asgi()), + re_path(r"ws/chats/(?P\d+)/$", consumers.ChatConsumer.as_asgi()), ] diff --git a/apps/chats/serializers.py b/apps/chats/serializers.py index eca42e7..18925a5 100644 --- a/apps/chats/serializers.py +++ b/apps/chats/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers from django.contrib.auth import get_user_model -from apps.chats.models import Chat, Message +from apps.chats.models import Message, Chat User = get_user_model() @@ -18,7 +18,7 @@ class Meta: class MessageSerializer(serializers.ModelSerializer): - user = UserSerializer() + user = serializers.StringRelatedField() class Meta: model = Message @@ -44,3 +44,32 @@ class Meta: "messages", "created_at", ) + + +# class MessageSerializer(serializers.ModelSerializer): +# user = UserSerializer() + +# class Meta: +# model = Message +# fields = ( +# "id", +# "chat", +# "user", +# "text", +# "created_at", +# ) + + +# class ChatSerializer(serializers.ModelSerializer): +# users = UserSerializer(many=True) +# messages = MessageSerializer(many=True, read_only=True) + +# class Meta: +# model = Chat +# fields = ( +# "id", +# "title", +# "users", +# "messages", +# "created_at", +# ) diff --git a/apps/chats/urls.py b/apps/chats/urls.py index 1958c62..cd86e92 100644 --- a/apps/chats/urls.py +++ b/apps/chats/urls.py @@ -1,17 +1,44 @@ +# from django.urls import path +# from . import views + +# urlpatterns = [ +# path("chats/", views.ChatListView.as_view(), name="chat-list"), +# path("chats//", views.ChatDetailView.as_view(), name="chat-detail"), +# path( +# "chats//messages/", views.MessageListView.as_view(), name="message-list" +# ), +# path( +# "chats//messages//", +# views.MessageDetailView.as_view(), +# name="message-detail", +# ), +# path("users/", views.UserListView.as_view(), name="user-list"), +# path("users//", views.UserDetailView.as_view(), name="user-detail"), +# ] + + +# urlpatterns = [ +# path("users/", views.UserListView.as_view(), name="user-list"), +# ] + +# urls.py from django.urls import path -from . import views +from .views import ( + ChatListCreateView, + ChatDetailView, + MessageListCreateView, + MessageDetailView, + UserListView, +) urlpatterns = [ - path("chats/", views.ChatListView.as_view(), name="chat-list"), - path("chats//", views.ChatDetailView.as_view(), name="chat-detail"), - path( - "chats//messages/", views.MessageListView.as_view(), name="message-list" - ), + path("", ChatListCreateView.as_view(), name="chat-list-create"), + path("/", ChatDetailView.as_view(), name="chat-detail"), path( - "chats//messages//", - views.MessageDetailView.as_view(), - name="message-detail", + "/messages/", + MessageListCreateView.as_view(), + name="message-list-create", ), - path("users/", views.UserListView.as_view(), name="user-list"), - path("users//", views.UserDetailView.as_view(), name="user-detail"), + path("messages//", MessageDetailView.as_view(), name="message-detail"), + path("users/", UserListView.as_view(), name="user-list"), ] diff --git a/apps/chats/views.py b/apps/chats/views.py index e1b2712..6dcfd49 100644 --- a/apps/chats/views.py +++ b/apps/chats/views.py @@ -1,32 +1,33 @@ from rest_framework import generics -from apps.chats import serializers, models +from apps.chats.models import Chat, Message, User +from apps.chats.serializers import ChatSerializer, MessageSerializer, UserSerializer -class UserListView(generics.ListAPIView): - queryset = models.User.objects.all() - serializer_class = serializers.UserSerializer +class UserListView(generics.ListAPIView): + queryset = User.objects.all() + serializer_class = UserSerializer -class UserDetailView(generics.RetrieveAPIView): - queryset = models.User.objects.all() - serializer_class = serializers.UserSerializer +class ChatListCreateView(generics.ListCreateAPIView): + queryset = Chat.objects.all() + serializer_class = ChatSerializer -class ChatListView(generics.ListCreateAPIView): - queryset = models.Chat.objects.all() - serializer_class = serializers.ChatSerializer +class ChatDetailView(generics.RetrieveUpdateDestroyAPIView): + queryset = Chat.objects.all() + serializer_class = ChatSerializer -class ChatDetailView(generics.RetrieveAPIView): - queryset = models.Chat.objects.all() - serializer_class = serializers.ChatSerializer +class MessageListCreateView(generics.ListCreateAPIView): + queryset = Message.objects.all() + serializer_class = MessageSerializer -class MessageListView(generics.ListAPIView): - queryset = models.Message.objects.all() - serializer_class = serializers.MessageSerializer + def get_queryset(self): + chat_id = self.kwargs.get("chat_id") + return Message.objects.filter(chat_id=chat_id) -class MessageDetailView(generics.RetrieveAPIView): - queryset = models.Message.objects.all() - serializer_class = serializers.MessageSerializer +class MessageDetailView(generics.RetrieveUpdateDestroyAPIView): + queryset = Message.objects.all() + serializer_class = MessageSerializer diff --git a/core/asgi.py b/core/asgi.py index 2348a13..02f06be 100644 --- a/core/asgi.py +++ b/core/asgi.py @@ -1,42 +1,67 @@ -# """ -# ASGI config for core project. +# # """ +# # ASGI config for core project. -# It exposes the ASGI callable as a module-level variable named ``application``. +# # It exposes the ASGI callable as a module-level variable named ``application``. + +# # For more information on this file, see +# # https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ +# # """ + +# # import os + +# # from django.core.asgi import get_asgi_application + +# # os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings") + +# # application = get_asgi_application() -# For more information on this file, see -# https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ -# """ # import os +# import django +# django.setup() # from django.core.asgi import get_asgi_application +# from channels.routing import ProtocolTypeRouter, URLRouter +# from channels.auth import AuthMiddlewareStack +# from apps.chats.consumers import ChatConsumer +# from django.urls import re_path -# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings") +# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "your_project_name.settings") -# application = get_asgi_application() +# application = ProtocolTypeRouter( +# { +# "http": get_asgi_application(), +# "websocket": AuthMiddlewareStack( +# URLRouter( +# [ +# re_path(r"ws/chat/(?P\d+)/$", ChatConsumer.as_asgi()), +# ] +# ) +# ), +# } +# ) -import os +# asgi.py import django django.setup() +import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter, URLRouter from channels.auth import AuthMiddlewareStack -from apps.chats.consumers import ChatConsumer -from django.urls import re_path +from apps.chats import routing + +import environ + +env = environ.Env() +env.read_env(".env") -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "your_project_name.settings") +# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings') application = ProtocolTypeRouter( { "http": get_asgi_application(), - "websocket": AuthMiddlewareStack( - URLRouter( - [ - re_path(r"ws/chat/(?P\d+)/$", ChatConsumer.as_asgi()), - ] - ) - ), + "websocket": AuthMiddlewareStack(URLRouter(routing.websocket_urlpatterns)), } )