我正在部署一个使用 django 频道构建的聊天应用程序。它在我的本地主机上工作,但在生产中,套接字首先连接,但一旦我发送消息,就会出现以下错误:WebSocket is already in CLOSING or CLOSED state.
可能出什么问题了?提前致谢
我的服务器日志如下:
错误日志
File "/home/ubuntu/django/virtualenv2/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 1774, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'UserLazyObject'
File "/home/ubuntu/django/virtualenv2/lib/python3.7/site-packages/channels/generic/websocket.py", line 175, in websocket_connect
await self.connect()
File "./chat/consumers.py", line 179, in connect
File "./chat/managers.py", line 24, in by_user
threads = self.get_queryset().filter(thread_type="personal")
我的consumers.py文件和managers.py文件如下。
Consumers.py 文件
from django.utils import timezone
import pytz, time, datetime
import json
from channels.layers import get_channel_layer
from chat.models import Message, Thread, Notification
from channels.consumer import SyncConsumer
from asgiref.sync import async_to_sync
from django.contrib.auth import get_user_model
from datetime import datetime
from django.dispatch import receiver
from django.db.models import signals
import asyncio
from asgiref.sync import async_to_sync, sync_to_async
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncJsonWebsocketConsumer
from django.utils import timezone
User = get_user_model()
# ================== Chat consumer starts ==================
class ChatConsumer(SyncConsumer):
def websocket_connect(self, event):
my_slug = self.scope['path'][-8:]
me = User.objects.get(slug=my_slug)
other_user_slug = self.scope['url_route']['kwargs']['other_slug']
other_user = User.objects.get(slug=other_user_slug)
self.thread_obj = Thread.objects.get_or_create_personal_thread(
me, other_user)
self.room_name = 'personal_thread_{}'.format(self.thread_obj.id)
async_to_sync(self.channel_layer.group_add)(
self.room_name, self.channel_name)
self.send({
'type': 'websocket.accept',
})
@staticmethod
@receiver(signals.post_save, sender=Notification)
def order_offer_observer(sender, instance, **kwargs):
layer = get_channel_layer()
thread_id = instance.thread.id
return thread_id
def websocket_receive(self, event):
my_slug = self.scope['path'][-8:]
me = User.objects.get(slug=my_slug)
other_user_slug = self.scope['url_route']['kwargs']['other_slug']
other_user = User.objects.get(slug=other_user_slug)
text = json.loads(event.get('text'))
thread_obj = Thread.objects.get_or_create_personal_thread(
me, other_user)
obj = Thread.objects.get_or_create_personal_thread(me, other_user)
recent_threads_id = []
other_user_threads = Thread.objects.by_user(other_user.id).all()
for one_thread in other_user_threads:
if one_thread.message_set.all():
if (one_thread.users).first().email == other_user.email:
y = Notification.objects.get_notification_object(
thread=obj, user1=other_user, user2=(one_thread.users).last())
y = y.read
recent_threads_id.append(one_thread.id)
else:
y = Notification.objects.get_notification_object(
thread=obj, user1=other_user, user2=(one_thread.users).first())
y = y.read
recent_threads_id.append(one_thread.id)
else:
pass
if "message" in text:
notification = Notification.objects.get_notification_object(
thread=thread_obj, user1=me, user2=other_user)
notification.sender = me
print("notification.sender " , notification.sender)
current_thread_id = self.order_offer_observer(
sender=Notification, instance=Notification.objects.get_notification_object(thread=thread_obj, user1=me, user2=other_user))
obj.updated_at = int(round(time.time() *1000))
obj.save()
fmt = "%I:%M %p"
utctime = datetime.now()
utc = utctime.replace(tzinfo=pytz.UTC)
localtz = utc.astimezone(timezone.get_current_timezone())
sent_time = localtz.strftime(fmt)
message_text = text['message']
msg = json.dumps({
'text': message_text,
'user_slug': my_slug,
'thread_id': current_thread_id,
'sent_time' : sent_time
})
# Sending live notifications
threads_count = len(recent_threads_id)
if threads_count < 1:
async_to_sync(self.channel_layer.group_send)(
self.room_name,
{'type': 'websocket.message',
'text': msg})
else:
for one_id in range(threads_count):
if recent_threads_id[one_id] == current_thread_id:
async_to_sync(self.channel_layer.group_send)(
self.room_name,
{'type': 'websocket.message',
'text': msg})
else:
async_to_sync(self.channel_layer.group_send)(
'personal_thread_{}'.format(recent_threads_id[one_id]),
{'type': 'websocket.message',
'text': repr(current_thread_id)})
if notification:
notification.read = False
notification.save()
self.store_message(message_text, sent_time)
elif "chat_read" in text:
notification = Notification.objects.get_notification_object(
thread=thread_obj, user1=me, user2=other_user)
if notification.sender:
if 'user_slug' in text:
chat_opener_slug = text['user_slug']
if chat_opener_slug != notification.sender.slug:
notification.read = True
notification.save()
async_to_sync(self.channel_layer.group_send)(
'personal_thread_{}'.format(obj.id),
{'type':'websocket.message',
'text': json.dumps({'message_read': "yes"})})
def websocket_message(self, event):
self.send({
'type': 'websocket.send',
'text': event.get('text')
})
def websocket_disconnect(self, event):
my_slug = self.scope['path'][-8:]
me = User.objects.get(slug=my_slug)
other_user_slug = self.scope['url_route']['kwargs']['other_slug']
other_user = User.objects.get(slug=other_user_slug)
thread_obj = Thread.objects.get_or_create_personal_thread(me, other_user)
# Deleting thread if it has no messages
if len(thread_obj.message_set.all()) == 0:
thread_obj.delete()
def store_message(self, text):
my_slug = self.scope['path'][-8:]
me = User.objects.get(slug=my_slug)
Message.objects.create(
thread=self.thread_obj,
sender=me,
text=text,
)
# ================== Chat consumer ends ==================
class NotifyConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
await self.accept()
await self.channel_layer.group_add("gossip", self.channel_name)
if self.scope['path'][-8:]:
current_user_slug = self.scope['path'][-8:]
current_user = User.objects.get(slug=current_user_slug)
current_users_chats = sync_to_async(Thread.objects.by_user(current_user).order_by('updated_at'))
@staticmethod
@receiver(signals.post_save, sender=Message)
def announce_new_user(sender, instance, **kwargs):
sender = instance.sender
channel_layer = get_channel_layer()
if instance.thread.users.first() == sender:
me = instance.thread.users.last()
else:
me = instance.thread.users.first()
async_to_sync(channel_layer.group_send)(
"gossip",{
"type": "user.gossip",
"event": "New user",
"sender": me.slug,
"receiver": sender.slug
}
)
async def user_gossip(self, event):
await self.send_json(event)
async def disconnect(self, close_code):
await self.channel_layer.group_discard("gossip", self.channel_name)
```
----------------------- Managers.py file ------------------
from datetime import datetime
from django.db import models
from django.shortcuts import Http404
from django.db.models import Count
class ThreadManager(models.Manager):
def get_or_create_personal_thread(self, user1, user2):
threads = self.get_queryset().filter(thread_type="personal")
threads = threads.filter(users__in=[user1, user2])
threads = threads.annotate(u_count=Count('users')).filter(u_count=2)
if threads.exists():
return threads.first()
else:
if (user1 == user2):
raise Http404
else:
thread = self.create(thread_type="personal")
thread.users.add(user1)
thread.users.add(user2)
return thread
def by_user(self, user):
return self.get_queryset().filter(users__in=[user])
class MessageManager(models.Manager):
def message_by_user(self, user):
return self.get_queryset.filter(sender__in=[user])