django distinct不仅返回唯一字段
我有一个包含三个字段的聊天信息模型: 发件人、收件人用户模型的ForeignKey和消息作为文本字段 我正在尝试选择与发件人或收件人字段exclude request.user的所有唯一对话。我对如何实现这一点有点困惑 我有两个问题:django distinct不仅返回唯一字段,django,django-views,distinct,Django,Django Views,Distinct,我有一个包含三个字段的聊天信息模型: 发件人、收件人用户模型的ForeignKey和消息作为文本字段 我正在尝试选择与发件人或收件人字段exclude request.user的所有唯一对话。我对如何实现这一点有点困惑 我有两个问题: Message.objects.filter(Q(sender = request.user)|Q(recipient = request.user)).values('sender').distinct() 即使使用order_by,也不会返回唯一记录的列表。
Message.objects.filter(Q(sender = request.user)|Q(recipient = request.user)).values('sender').distinct()
即使使用order_by,也不会返回唯一记录的列表。我有很多完全相同的发件人:{'sender':4L},{'sender':4L}收件人也是如此
第二个问题是:
我是否需要连接发件人和收件人的两个问题集,或者有其他方法获取当前request.user的整个对话列表
upd。好的,这是表格内容:
mysql> select id, sender_id, recipient_id, body from messages_message ;
+----+-----------+--------------+-----------+
| id | sender_id | recipient_id | body |
+----+-----------+--------------+-----------+
| 1 | 4 | 1 | Message 1 |
| 2 | 4 | 1 | Message 2 |
+----+-----------+--------------+-----------+
在这里,它是
Message.objects.filter(Q(sender = request.user)|Q(recipient = request.user)).values('sender').distinct()
[{'sender': 4L}, {'sender': 4L}]
但我只希望得到一个[{'sender':4L}]
那么,怎么了
upd2。我的模型:
class Message(models.Model):
body = models.TextField(_("Body"))
sender = models.ForeignKey(User, related_name='sent_messages', verbose_name=_("Sender"))
recipient = models.ForeignKey(User, related_name='received_messages', null=True, blank=True, verbose_name=_("Recipient"))
sent_at = models.DateTimeField(_("sent at"), null=True, blank=True)
我需要选择所有发送或接收消息的对话伙伴。当前用户的request.user。正如Rob指出的,distinct的工作方式与您预期的不同。它查看所有字段以确定唯一性,而不仅仅是在值中指定的字段
如果您使用的是PostgreSQL,那么您可以通过将参数传递给distinct来做您想做的事情。从:
您可以传递位置参数*字段以指定
应应用DISTINCT的字段的名称。这意味着
SQL查询上的SELECT DISTINCT。区别就在这里。对于一个正常的
调用时,数据库会比较每行中的每个字段
确定哪些行是不同的。对于一个与
指定字段名时,数据库将仅比较指定的
字段名
回到找到所有谈话伙伴的最终目标,我看不到一个简单、优雅的解决方案。一种方法是使用聚合:
receivers = user.sent_messages.values('recipient')
.aggregate(num_messages=Count('id'))
senders = user.received_messages.values('sender')
.aggregate(num_messages=Count('id'))
如果您不关心发送者和接收者之间的区别,那么您可能希望手动组合它们。就我的$.02而言,我真的认为python比SQL更好地处理这种逻辑。如果您使用特定于一个DB的查询参数,那么在我看来,这有点违背了ORM的目的 我想试试这样的东西:
messages = Message.objects.filter(Q(sender = request.user)|Q(recipient = request.user))
## Does this need to be 'Q'? ##
然后:
如果要经常查看此集合,可以将其缓存
但最好让合作伙伴成为一个用户域,并在每次发送消息时添加到其中。这样就不需要进行复杂的查询,只需要一个简单的User.partners
我假设您无论如何都需要让用户对象发送消息,因此不会产生额外的开销。您确定那里没有唯一的记录吗?它们可能具有相同的发件人,但具有不同的PK。在我看来,您的查询将给出您在问题的第二部分中提出的问题。@RobL我已更新了问题。您的评论不清楚,distinct是否总是通过pk返回unique?我认为它将返回值中的unique-based字段。这不是DISTINCT所做的。Distinct返回唯一的行,这就是它在这里所做的。因为每一条消息都是唯一的,所以它会被返回。如果有一个JOIN子句导致返回多行,但它们实际上引用了同一父行,那么DISTINCT将起作用。您可能想使用GROUP_BY。但是要小心,它通常是性能杀手。我不确定您真正想要的是什么,但是如果您想要不同的发件人,那么您应该从该表中选择。如果我们可以从models.py中看到您的模型,那么将更容易帮助您解决。@RobL我需要在django中对特定字段执行一种排序| uniq操作。模型现在有问题。
partners = set()
for m in messages:
partners.add(m.sender)
partners.add(m.recipient)