我正在开发聊天应用程序。这些模型是:
User:
name
和
Message:
user = ForeignKeyField(User, related_name="messages"),
message,
time
现在,数据库中只有两个用户。可以说消息对象就像:
msg1:user1:“你好”
msg2:user1:“你好吗?”
msg3:user2:“我很好。”
msg4:user1:“怎么了?”
msg5:user2:“没什么。”
msg6:user2:“嗯。”
现在我需要按顺序获取消息(比如说json):
{user1:[msg1, msg2], user2:[msg3], user1:[msg4], user2:[msg5, msg6]}
我需要在查询集中对其进行过滤,例如:
Message.objects.filter(....).order(....)
***此处使用json进行了解。
好的。如果无法在查询集中实现。然后,将以下示例作为示例模板:
<div class="chat">
<div class="photo">
</div>
<div class="msg"></div>
<div class="msg"></div>
</div>
我如何实现它:
{% for msg in msgs %}
<div class="chat">
<div class="photo">
</div>
<div class="msg">msg.message</div>
<div class="msg">msg.message</div>//this should happen only if msg.user is same as previous msg.user
</div>
{% endfor %}
那怎么办?我知道django的ifchanged
控件。但是我无法使用它。
答案 0 :(得分:1)
由于字典(在Python和JSON中都可以)仅包含键一次,因此上述含义没有多大意义。因此,您不能有两次包含user1
的字典。
但是,我们可以使用一个包含2个元组的可迭代对象:一个包含user
作为左边项目的元组,并在第二个消息中包含“ burst ”消息。像这样:
[
(user1, [msg1, msg2]),
(user2, [msg3]),
(user1, [msg4]),
(user2, [msg5, msg6])
]
我们可以通过在视图中添加一些处理来做到这一点。作为查询,我们首先按Message
对time
进行排序,然后也提取user
。接下来,我们使用itertools.groupby
对每个用户进行分组,例如:
from itertools import groupby
from operator import attrgetter
qs = Message.objects.select_related('user').order_by('time')
all_msgs = [(u, list(ms)) for (u, ms) in groupby(qs, attrgetter('user'))]
return render(request, 'template.html', {'all_msgs': all_msgs})
然后在模板中,我们在2元组上渲染,然后分别在消息上渲染:
{% for user, msgs in all_msgs %}
<div class="chat">
<div class="photo">{{ user.photo }}
</div>
{% for msg in msgs %}
<div class="msg">msg.message</div>
{% endfor %}
</div>
{% endfor %}
在for
循环中,您当然仍然必须填写数据。例如{{ user.photo }}
(如果存在)。