11

在评论模型的任何字段上运行 distinct() 总是返回所有记录,

Comment.objects.values('user').distinct()

[{'user': 1}, {'user': 0}, {'user': 0}, {'user': 0}, {'user': 0}, {'user': 1}, { “用户”:1},{“用户”:1},{“用户”:1}]

Comment.objects.values('ip_address').distinct()

[{'ip_address': u'127.0.0.1'},{'ip_address': u'192.168.0.180'}, {'ip_address':u'192.168.0.180'}, {'ip_address': u'192.168.0.180 '}, {'ip_address': u'192.168.0. 180'}, {'ip_address': u'192.168.0.180'}, {'ip_address': u'192.168.0.180'}, {'ip_address': u'192.168.0.180'}, {'ip_address': u' 192.168.0.180'}]

为什么会这样?有没有解决的办法?谢谢!

ps: distinct() 在我的测试过程中在自定义模型的不同类型字段中运行得非常好。评论框架有什么特别之处吗?

一点结论 感谢大家回答这个问题,结合一些阅读,我得出以下结论:

  1. values() 影响最终 sql 的 SELECT 部分中的查找字段(“ values() 采用可选的位置参数 *fields,它指定 SELECT 应限制的字段名称”)
  2. order_by() 也将其参数添加到 SELECT 部分。
  3. 在查找中使用 distinct() 将导致 sql 如下所示:

    SELECT DISTINCT [fields1, fields2, fields3] FROM ... WHERE ...

    并且这些字段的值共同决定了一条记录是否唯一。这些字段可能来自查找中的 values() 或 order_by() 函数。

  4. 因此 order_by() 与 distinct() 结合时会增加一些不需要的效果,order_by 中指定的字段也考虑了记录是否唯一

  5. Django Comment 默认有一个隐藏的 order_by 参数,从而造成了整个问题。任何模型在返回 qs 时都有隐藏的 order_by 可能会导致相同的问题。

  6. 解决的方法是在查找的末尾添加一个空的order_by(),这样就去掉了默认的order_by。
4

3 回答 3

18
Comment.objects.values('user').distinct().order_by()
于 2012-01-26T12:20:11.930 回答
6

I haven't verified that this is the cause, but Comment model has a default ordering which influences distinct() method:

In [1]: print Comment.objects.values('ip_address').distinct().query
SELECT DISTINCT "django_comments"."ip_address", "django_comments"."submit_date" FROM "django_comments" ORDER BY "django_comments"."submit_date" ASC

It's a documented feature.

Now, how could it be that two comments have exactly the same timestamp? I suppose you're using MySQL which doesn't support anything less than a second.

And if you want to get rid of the default ordering, just do:

Comment.objects.order_by().values('ip_address').distinct()
于 2012-01-26T13:05:11.677 回答
1

您可以将查询包装在集合中;

根据文档, distinct() 与 values() 配合得不好

ip_sets = set(Comment.objects.order_by().values('ip_address'))
ip_list = list(set(Comment.objects.order_by().values('ip_address')))
于 2021-03-22T07:21:38.420 回答