Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ORM returning the same values multiple times when using .distinct()

When using .distinct() on a set of objects, the same values are being repeated over and over, which defeats the purpose of using .distinct()

An example from a project I'm working on:

In [5]: Section.objects.filter(module=15).values('section').distinct()
Out[5]: [{'section': '1'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, {'section': '2'}, '...(remaining elements truncated)...']

Why is it returning each value instead of only the distinct ones?

For reference, here is my model:

class Section(models.Model):
    module = models.ForeignKey(Module, on_delete=models.CASCADE)
    title = models.CharField(max_length=400)
    section = models.CharField(max_length=3)
    topic = models.CharField(max_length=3)
    subtopic = models.CharField(max_length=3)
    subsubtopic = models.CharField(max_length=3)
    language = models.CharField(max_length=2)
    def __str__(self):
        return self.sectionid() + " - " + self.title
    def sectionid(self):
        return self.module.moduleid + ": " + self.justsectionid()
    def justsectionid(self):
        return self.section + "." + self.topic + "." + self.subtopic + \
        self.subsubtopic + "-" + self.language
    class Meta:
        ordering = ['section', 'topic', 'subtopic', 'subsubtopic', 'language']
like image 452
Anna Avatar asked Feb 27 '26 05:02

Anna


1 Answers

There is an issue with .distinct() with the Django ORM where this behavior will happen if you use meta ordering. In order for this to work as expected, you need to reset the ordering to the default. You can do this with a blank call to .order_by() as follows:

In [6]: Section.objects.filter(module=15).order_by().values('section').distinct()
Out[6]: [{'section': '1'}, {'section': '2'}, {'section': '3'}]
like image 99
Anna Avatar answered Feb 28 '26 18:02

Anna