如何像在正常聊天中一样根据发送时间对消息进行排序?
How to order messages based on the time its send like in normal chats?
大家好,我无法像在正常聊天中那样根据时间戳对消息进行排序。怎么做?谁能给我一个合适的解决方案?我已经用我使用的模型管理器更新了问题。
这是模型。
class Chat(models.Model):
first_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='first_user_chat', null=True)
second_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='second_user_chat', null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class ChatMessage(models.Model):
chat = models.ForeignKey(Chat, blank=True, null=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='sender', on_delete=models.CASCADE)
message = models.TextField()
# read = models.BooleanField(blank=False, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
观看次数
class ChatView(LoginRequiredMixin, FormMixin, DetailView):
template_name = 'messenger/chat.html'
form_class = ComposeForm
success_url = './'
def get_queryset(self):
return Chat.objects.by_user(self.request.user).order_by('-timestamp')
def get_object(self):
other_username = self.kwargs.get("username")
obj, created = Chat.objects.get_or_new(self.request.user, other_username)
if obj == None:
raise Http404
return obj
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['messages'] = ChatMessage.objects.filter(user=self.request.user).order_by('-timestamp')
context['form'] = self.get_form()
return context
def post(self, request, *args, **kwargs):
if not self.request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
chat = self.get_object()
user = self.request.user
message = form.cleaned_data.get("message")
ChatMessage.objects.create(user=user, chat=chat, message=message)
return super().form_valid(form)
这是我用来渲染的模板。这也有所有 javascript 代码。
{% load static %}
{% static "channels/js/websocketbridge.js" %}
{% block content %}
<a class="btn btn-light" href="{% url 'messenger:inboxview' %}">Back to Inbox</a>
<div class="msg_history offset-md-1" id="chat-items">
{% for chat in object.chatmessage_set.all %}
{% if chat.user == user %}
<div class="outgoing_msg">
<div class="outgoing_msg_img">
<img class="rounded-circle" style="height: 30px; width: 30px; margin-right: 16px;"
src="{{ chat.user.profile.profile_pic.url }}">
</div>
<div class="sent_msg">
<p>
<div>
{{ chat.message }}
</div>
<small><span style="font-size: 6" class="time_date"> {{ chat.timestamp }}</span></small>
</p>
</div>
</div>
{% else %}
<div class="incoming_msg offset-md-8">
<div class="incoming_msg_img">
<img class="rounded-circle offset-md-7" style="height: 30px; width: 30px; margin-right: 16px;" src="{{ chat.user.profile.profile_pic.url }}">
</div>
<div class="received_msg">
<div class="received_withd_msg">
<p>
<div>
{{ chat.message }}
</div>
<small><span style="font-size: 6" class="time_date"> {{ chat.timestamp }}</span></small>
</p>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="type_msg offset-md-1">
<div class="input_msg_write">
<!-- text input / write message form -->
<form id='form' method='POST'>
{% csrf_token %}
<input type='hidden' id='myUsername' value='{{ user.username }}' />
{{ form.as_p }}
<center><button type="submit" class='btn btn-success disabled' value="Send">Send</button></center>
</form>
</div>
</div>
{% block javascript %}
<script src='https://cdnjs.cloudflare.com/ajax/libs/reconnecting-websocket/1.0.0/reconnecting-websocket.js'></script>
<script type="text/javascript">
// websocket scripts - client side*
console.log(window.location)
var loc = window.location
var formData = $("#form")
var msgInput = $("#id_message")
var chatHolder = $('#chat-items')
var me = $('#myUsername').val()
var wsStart = 'ws://'
if (loc.protocol == 'https:') {
wsStart = 'wss://'
}
var endpoint = wsStart + loc.host + loc.pathname
var socket = new ReconnectingWebSocket(endpoint)
// below is the message I am receiving
socket.onmessage = function(e) {
console.log("message", e)
var data = JSON.parse(event.data);
// Find the notification icon/button/whatever and show a red dot, add the notification_id to element as id or data attribute.
var chatDataMsg = JSON.parse(e.data)
chatHolder.append('<li>' + chatDataMsg.message + ' from ' + ' - ' + chatDataMsg.username + '</li>')
}
// below is the message I am sending
socket.onopen = function(e) {
console.log("open", e)
formData.submit(function(event) {
event.preventDefault()
var msgText = msgInput.val()
var finalData = {
'message': msgText
}
socket.send(JSON.stringify(finalData))
formData[0].reset()
})
}
socket.onerror = function(e) {
console.log("error", e)
}
socket.onclose = function(e) {
console.log("close", e)
}
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const webSocketBridge = new channels.WebSocketBridge();
webSocketBridge.connect('/ws');
webSocketBridge.listen(function(action, stream) {
console.log("RESPONSE:", action);
})
document.ws = webSocketBridge; /* for debugging */
})
</script>
{% endblock %}
{% endblock %}
请告诉我正确的做法。
谢谢!
请试试这个:
在models.py
中添加class元:
class ChatMessage(models.Model):
chat = models.ForeignKey(Chat, blank=True, null=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='sender', on_delete=models.CASCADE)
message = models.TextField()
# read = models.BooleanField(blank=False, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-timestamp"]
如果这可行,那是因为在模板中您是这样迭代的:{% for chat in object.chatmessage_set.all %}
未排序。
我看到的另一件事是你没有使用这个:context['messages'] = ChatMessage.objects.filter(user=self.request.user).order_by('-timestamp')
但我会用这样的东西来改变:
chat = self.get_object()
context["messages"] = chat.chatmessage_set.all().order_by("-timestamp")
并在模板中使用它来迭代而不是 object.chatmessage_set.all
大家好,我无法像在正常聊天中那样根据时间戳对消息进行排序。怎么做?谁能给我一个合适的解决方案?我已经用我使用的模型管理器更新了问题。
这是模型。
class Chat(models.Model):
first_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='first_user_chat', null=True)
second_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='second_user_chat', null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class ChatMessage(models.Model):
chat = models.ForeignKey(Chat, blank=True, null=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='sender', on_delete=models.CASCADE)
message = models.TextField()
# read = models.BooleanField(blank=False, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
观看次数
class ChatView(LoginRequiredMixin, FormMixin, DetailView):
template_name = 'messenger/chat.html'
form_class = ComposeForm
success_url = './'
def get_queryset(self):
return Chat.objects.by_user(self.request.user).order_by('-timestamp')
def get_object(self):
other_username = self.kwargs.get("username")
obj, created = Chat.objects.get_or_new(self.request.user, other_username)
if obj == None:
raise Http404
return obj
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['messages'] = ChatMessage.objects.filter(user=self.request.user).order_by('-timestamp')
context['form'] = self.get_form()
return context
def post(self, request, *args, **kwargs):
if not self.request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
chat = self.get_object()
user = self.request.user
message = form.cleaned_data.get("message")
ChatMessage.objects.create(user=user, chat=chat, message=message)
return super().form_valid(form)
这是我用来渲染的模板。这也有所有 javascript 代码。
{% load static %}
{% static "channels/js/websocketbridge.js" %}
{% block content %}
<a class="btn btn-light" href="{% url 'messenger:inboxview' %}">Back to Inbox</a>
<div class="msg_history offset-md-1" id="chat-items">
{% for chat in object.chatmessage_set.all %}
{% if chat.user == user %}
<div class="outgoing_msg">
<div class="outgoing_msg_img">
<img class="rounded-circle" style="height: 30px; width: 30px; margin-right: 16px;"
src="{{ chat.user.profile.profile_pic.url }}">
</div>
<div class="sent_msg">
<p>
<div>
{{ chat.message }}
</div>
<small><span style="font-size: 6" class="time_date"> {{ chat.timestamp }}</span></small>
</p>
</div>
</div>
{% else %}
<div class="incoming_msg offset-md-8">
<div class="incoming_msg_img">
<img class="rounded-circle offset-md-7" style="height: 30px; width: 30px; margin-right: 16px;" src="{{ chat.user.profile.profile_pic.url }}">
</div>
<div class="received_msg">
<div class="received_withd_msg">
<p>
<div>
{{ chat.message }}
</div>
<small><span style="font-size: 6" class="time_date"> {{ chat.timestamp }}</span></small>
</p>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="type_msg offset-md-1">
<div class="input_msg_write">
<!-- text input / write message form -->
<form id='form' method='POST'>
{% csrf_token %}
<input type='hidden' id='myUsername' value='{{ user.username }}' />
{{ form.as_p }}
<center><button type="submit" class='btn btn-success disabled' value="Send">Send</button></center>
</form>
</div>
</div>
{% block javascript %}
<script src='https://cdnjs.cloudflare.com/ajax/libs/reconnecting-websocket/1.0.0/reconnecting-websocket.js'></script>
<script type="text/javascript">
// websocket scripts - client side*
console.log(window.location)
var loc = window.location
var formData = $("#form")
var msgInput = $("#id_message")
var chatHolder = $('#chat-items')
var me = $('#myUsername').val()
var wsStart = 'ws://'
if (loc.protocol == 'https:') {
wsStart = 'wss://'
}
var endpoint = wsStart + loc.host + loc.pathname
var socket = new ReconnectingWebSocket(endpoint)
// below is the message I am receiving
socket.onmessage = function(e) {
console.log("message", e)
var data = JSON.parse(event.data);
// Find the notification icon/button/whatever and show a red dot, add the notification_id to element as id or data attribute.
var chatDataMsg = JSON.parse(e.data)
chatHolder.append('<li>' + chatDataMsg.message + ' from ' + ' - ' + chatDataMsg.username + '</li>')
}
// below is the message I am sending
socket.onopen = function(e) {
console.log("open", e)
formData.submit(function(event) {
event.preventDefault()
var msgText = msgInput.val()
var finalData = {
'message': msgText
}
socket.send(JSON.stringify(finalData))
formData[0].reset()
})
}
socket.onerror = function(e) {
console.log("error", e)
}
socket.onclose = function(e) {
console.log("close", e)
}
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const webSocketBridge = new channels.WebSocketBridge();
webSocketBridge.connect('/ws');
webSocketBridge.listen(function(action, stream) {
console.log("RESPONSE:", action);
})
document.ws = webSocketBridge; /* for debugging */
})
</script>
{% endblock %}
{% endblock %}
请告诉我正确的做法。
谢谢!
请试试这个:
在models.py
中添加class元:
class ChatMessage(models.Model):
chat = models.ForeignKey(Chat, blank=True, null=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='sender', on_delete=models.CASCADE)
message = models.TextField()
# read = models.BooleanField(blank=False, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-timestamp"]
如果这可行,那是因为在模板中您是这样迭代的:{% for chat in object.chatmessage_set.all %}
未排序。
我看到的另一件事是你没有使用这个:context['messages'] = ChatMessage.objects.filter(user=self.request.user).order_by('-timestamp')
但我会用这样的东西来改变:
chat = self.get_object()
context["messages"] = chat.chatmessage_set.all().order_by("-timestamp")
并在模板中使用它来迭代而不是 object.chatmessage_set.all