类型错误:字段 'id' 需要一个数字,但在 0x7f3e01742e90 处得到 <channels.auth.UserLazyObject 对象>

时间:2021-03-25 18:39:39

标签: python django websocket django-channels

我正在部署一个使用 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])


0 个答案:

没有答案