Running distinct() on any field of the comment model always returns all the records,
Comment.objects.values('user').distinct()
[{'user': 1}, {'user': 0}, {'user': 0}, {'user': 0}, {'user': 0}, {'user': 1}, {'user': 1}, {'user': 1}, {'user': 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'}]
Why is this happening? Is there a way around this? Thanks!
ps: distinct() does run very well in different types of fields of a custom model during my test. Something special about the Comments framework?
Bit of conclusion Thanks everybody answering this question, combined with some reading I get conclusion as following:
- values() influences the lookup fields in SELECT part of the final sql("values() takes optional positional arguments, *fields, which specify field names to which the SELECT should be limited")
- order_by() adds its parameter to the SELECT part as well.
using distinct() in a look up will result the sql to look like this:
SELECT DISTINCT [fields1, fields2, fields3] FROM ... WHERE...
and the values of the fields all together decides whether a record is unique. The fields may come from values() or order_by() functions in the lookup.
Django Comment has a hidden order_by parameter by default, thus creating the whole problem. Any model has a hidden order_by when returning the qs can cause the same problem.
- The way of solving it is by adding an empty order_by() at the end of the lookup, which removes the default order_by.
I haven't verified that this is the cause, but
Comment
model has a default ordering which influencesdistinct()
method: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: