Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

OR operator in Django filter creates duplicates

when I print Brand.objects.filter(Q(name__icontains=keyword)|Q(tag__name__icontains=keyword)), it yields two objects as opposed to my expectation. It should be only one.

My models.py is like

class Brand(models.Model):
    name = models.CharField(max_length=20)
    tag = models.ManyToManyField('Tag', blank=True)
class Tag(models.Model):
    name = models.CharField(max_length=20)

When I print Brand.objects.filter(name__icontains=keyword) and Brand.objects.filter(tag__name__icontains=keyword) seperately, each one yields only one same object. But when I merge these two queries, it yields duplicates. I found out .distinct() solves this problem but I wanna know why. Looking forward to help!

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

It is not the or condition that results in duplicates, it is the fact that you are filtering on a related model with a ManyToManyField. This means that the query will look like:

SELECT brand.*
FROM brand
LEFT OUTER JOIN brand_tag ON brand_tag.brand_id = brand.id
LEFT OUTER JOIN tag ON tag.id = brand_tag.tag_id
WHERE brand.name LIKE %keyword% OR tag.name LIKE %keyword%

You thus will JOIN on the tag model, and if multiple tags match the keyword, then that brand will be repeated that many times in the QuerySet.

If you thus would have filtered with .filter(tag__name__icontains=keyword), you would have gotten duplicates as well.


Note: There is a django-taggit package [GitHub] to work with content that contains tags. This might be better than implementing your own tag system.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading