【问题标题】:How to look ahead and order a queryset in django?如何在 django 中展望并订购查询集?
【发布时间】:2018-07-29 14:22:08
【问题描述】:

我正在开发一个聊天应用程序。这些模型是:

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来理解。

  • 如何做到这一点?
  • 有什么缺点吗?
  • 之后我将在模板中渲染它。那么,是否可以使用 for 循环在模板内订购相同的东西?

好的。如果这不能在查询集中实现。然后让下面的一个作为示例模板:

<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 控制。但我无法使用它。

【问题讨论】:

  • 这没有多大意义,因为一个字典只能包含一个键一次,你的字典包含user1user2两次。
  • 但是,您可以使用例如元组的列表(在 JSON 中它是列表的列表)。其中每个元组包含 2 个元素;用户和消息列表。
  • 此外,我不清楚msg1 应该包含什么。一个字符串(消息)?那么user1 是什么? integer(id)?
  • 没有。不要考虑json。我用json来理解。我需要一个查询集。
  • 但是查询集通常不包含映射到列表的键(除非 字段 是列表)。

标签: django django-models django-views django-queryset


【解决方案1】:

以上内容没有多大意义,因为字典(Python 和 JSON 中的)只能包含一个键一次。因此,您不能拥有包含两次 user1 的字典。

然而,我们可以使用一个包含 2 元组的迭代:一个元组包含一个 user 作为左边的项目,第二个是消息的“burst”。所以像:

[
  (user1, [msg1, msg2]),
  (user2, [msg3]),
  (user1, [msg4]),
  (user2, [msg5, msg6])
]

我们可以通过在视图中添加一些处理来做到这一点。作为查询,我们首先按timeMessages 进行排序,然后我们也获取users。接下来我们使用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 }}(假设存在)。

【讨论】:

  • 我不能一次又一次地表示感谢。你太有帮助了。你现在有粉丝了。我希望我应该像你一样。我可以知道你是怎么学会这些的吗?
猜你喜欢
  • 2023-03-10
  • 2013-01-12
  • 2021-03-31
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 2020-08-30
  • 2021-07-02
  • 2018-01-01
相关资源
最近更新 更多