Python 保存通知对象django websockets的逻辑
在一个双人Python 保存通知对象django websockets的逻辑,python,django,django-views,django-channels,Python,Django,Django Views,Django Channels,在一个双人Django频道websockets聊天应用程序中,当从另一个other_用户收到消息时,我很难思考如何保存通知 现在我有一个函数def create_notification,在def create_chat_message之后调用 def create_chat_message每次在线程中发送新消息时,都会创建一个新的ChatMessage对象。它需要argsthread=thread\u obj,user=me,message=msg,因此显然每个消息都是与用户一起保存的,而不是
Django频道
websockets聊天应用程序中,当从另一个other_用户
收到消息时,我很难思考如何保存通知
现在我有一个函数def create_notification
,在def create_chat_message
之后调用
def create_chat_message
每次在线程中发送新消息时,都会创建一个新的ChatMessage
对象。它需要argsthread=thread\u obj,user=me,message=msg
,因此显然每个消息都是与用户一起保存的,而不是发送的
def create_notification
通过ChatMessage
中的id
获取最后一个对象,并创建一个新的notification
对象
created_notification = Notification.objects.create(notification_user=user, notification_chat=last_chat)
因此,从本质上讲,发送消息的人与notification
模型中的notification\u user
字段相关联,并与ChatMessage
id一起保存
但是,如果我向Tom发送消息,我发送的消息应该只与Tom的通知关联,而不是我自己
当我去渲染通知对象时,我会得到所有这些对象的列表,包括我发送的消息的通知
我如何为我与不同用户在一起的每个线程呈现所有通知
我把这些存错了吗?我是否应该配置保存通知功能,使其仅保存来自其他用户的传入消息?或者添加某种类型的if语句
我是否需要以某种方式与通知相关联,以便当它们呈现出来时,我作为收件人的所有通知都会显示出来
我的通知
模型将聊天信息
作为外键
,它有一个线程
字段,这是一个外键
到线程
,它包含第一个
和第二个
(在一个线程中代表我和另一个用户)
我已经看了好几天了,有种感觉我错过了一些简单的东西,让事情变得比需要的复杂得多
models.py
class ThreadManager(models.Manager):
def by_user(self, user):
qlookup = Q(first=user) | Q(second=user)
qlookup2 = Q(first=user) & Q(second=user)
qs = self.get_queryset().filter(qlookup).exclude(qlookup2).distinct()
return qs
# method to grab the thread for the 2 users
def get_or_new(self, user, other_username): # get_or_create
username = user.username
if username == other_username:
return None, None
# looks based off of either username
qlookup1 = Q(first__username=username) & Q(second__username=other_username)
qlookup2 = Q(first__username=other_username) & Q(second__username=username)
qs = self.get_queryset().filter(qlookup1 | qlookup2).distinct()
if qs.count() == 1:
return qs.first(), False
elif qs.count() > 1:
return qs.order_by('timestamp').first(), False
else:
Klass = user.__class__
try:
user2 = Klass.objects.get(username=other_username)
except Klass.DoesNotExist:
user2 = None
if user != user2:
obj = self.model(
first=user,
second=user2
)
obj.save()
return obj, True
return None, False
class Thread(models.Model):
first = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_first')
second = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_second')
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = ThreadManager()
def __str__(self):
return f'{self.id}'
@property
def room_group_name(self):
return f'chat_{self.id}'
def broadcast(self, msg=None):
if msg is not None:
broadcast_msg_to_chat(msg, group_name=self.room_group_name, user='admin')
return True
return False
class ChatMessage(models.Model):
thread = models.ForeignKey(Thread, null=True, blank=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='sender', on_delete=models.CASCADE)
message = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.id}'
class Notification(models.Model):
notification_user = models.ForeignKey(User, on_delete=models.CASCADE)
notification_chat = models.ForeignKey(ChatMessage, on_delete=models.CASCADE)
notification_read = models.BooleanField(default=False)
def __str__(self):
return f'{self.id} attached to {self.notification_user}'
消费者.py
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
print('connected', event)
other_user = self.scope['url_route']['kwargs']['username']
me = self.scope['user']
#print(other_user, me)
thread_obj = await self.get_thread(me, other_user)
self.thread_obj = thread_obj
chat_room = f"thread_{thread_obj.id}"
self.chat_room = chat_room
# below creates the chatroom
await self.channel_layer.group_add(
chat_room,
self.channel_name
)
await self.send({
"type": "websocket.accept"
})
async def websocket_receive(self, event):
# when a message is recieved from the websocket
print("receive", event)
message_type = json.loads(event.get('text','{}')).get('type')
print(message_type)
if message_type == "notification_read":
user = self.scope['user']
username = user.username if user.is_authenticated else 'default'
# Update the notification read status flag in Notification model.
notification = Notification.objects.filter(notification_user=user)
notification.notification_read = True
notification.save() #commit to DB
print("notification read")
return
front_text = event.get('text', None)
if front_text is not None:
loaded_dict_data = json.loads(front_text)
msg = loaded_dict_data.get('message')
user = self.scope['user']
username = user.username if user.is_authenticated else 'default'
notification_id = 'default'
myResponse = {
'message': msg,
'username': username,
'notification': notification_id,
}
print(myResponse)
await self.create_chat_message(user, msg)
await self.create_notification(user, msg)
# broadcasts the message event to be sent, the group send layer
# triggers the chat_message function for all of the group (chat_room)
await self.channel_layer.group_send(
self.chat_room,
{
'type': 'chat_message',
'text': json.dumps(myResponse)
}
)
# chat_method is a custom method name that we made
async def chat_message(self, event):
# sends the actual message
await self.send({
'type': 'websocket.send',
'text': event['text']
})
async def websocket_disconnect(self, event):
# when the socket disconnects
print('disconnected', event)
@database_sync_to_async
def get_thread(self, user, other_username):
return Thread.objects.get_or_new(user, other_username)[0]
@database_sync_to_async
def create_chat_message(self, me, msg):
thread_obj = self.thread_obj
return ChatMessage.objects.create(thread=thread_obj, user=me, message=msg)
@database_sync_to_async
def create_notification(self, user, msg):
last_chat = ChatMessage.objects.latest('id')
created_notification = Notification.objects.create(notification_user=user, notification_chat=last_chat)
print(created_notification)
return created_notification
navbar.html
<div id="notificationsBody" class="notifications">
{% for notifications in notification|slice:"0:10" %}
<a href="{% url 'chat:thread' user %}">
<span id="notification-{{notification.id}}">
{{ notifications.notification_chat.message }}
via {{ notifications.notification_chat.user }}
at {{ notifications.notification_chat.timestamp }}
</span>
</a>
{% endfor %}
{通知中通知的百分比|切片:“0:10”%}
{%endfor%}
要创建的通知
对象,需要将通知.通知用户
设置为其他用户
。通知针对的是其他用户,而不是发送消息的用户
other_username = self.scope['url_route']['kwargs']['username']
other_user = User.objects.get(username=other_username)
await self.create_notification(other_user, msg) #other_user, not the current user
但是,当将通知更新为已读时,需要当前用户。Hi!,不回答,但需要任何方式Notification.objects.filter(Notification\u user=user)
-->Notification.objects.filter(Notification\u user=user).update(Notification\u read=True)
,不需要Notification.Notification\u read=True
和Notification.save()
@BearBrownСПаабб:)很高兴听到这个消息,真的很酷!:)好的,当您说当更新通知为read时,当前用户是必需的,那么在通知
模型中,当前用户在哪里使用?它只有与其他用户关联的通知用户
字段
对吗?同时更改为其他用户
会出现错误无法分配“'james'”:“通知。通知用户”必须是“用户”实例。
但是james
是一个用户实例,这是因为我将james作为字符串传递,我假设我在other\u user
下面添加了一行,就像这样other\u user=user.objects.get(username=other\u user)
是的..你需要user
实例。假设您有两个用户,A
和B
,A
发送一条消息,那么Notification
对象将用户设为B
。因此,当B
读取通知并且其客户端将消息发送到服务器时,当前用户是B
,因此将有notification
实例使用Foreignkey
发送到B