Search code examples
djangomanytomanyfield

django manytomany order_by number of relationships


I have a manytomany relationship with Products and Tags, and I want to find the products that match my set of tags the best.

class Product(models.Model):
    def __str__(self):
        return self.title
    title = models.CharField(max_length=200)
    price = models.IntegerField()
    tags = models.ManyToManyField(Tag, related_name="products", blank=True)

class Tag(models.Model):
    def __str__(self):
        return self.name
    name = models.CharField(max_length=50)

I have a Queryset of tags and I want to order my products by whichever products have the most of the selected tag?

Are there any neat tricks to doing this? Or do I have to just query for all the Products and then sort them myself?

For instance, if I have a QuerySet with 3 tags: STEM, Programming, K-6

and I have products:

Computer Science Book (Programming),
Engineering Puzzle (K-6, STEM),
Cookie Cutters (K-6),
Rocket (STEM, K-6, Programming),
Backpack (K-6)

I want to return those same items but in this order:

Rocket (STEM, K-6, Programming),
Engineering Puzzle (K-6, STEM),
Computer Science Book (Programming),
Cookie Cutters (K-6),
Backpack (K-6)

Solution

  • If you want to sort the queryset based on 'Many' relationships (ManyToMany or ForeignKey) count, then do the following.

    from django.db.models import Count
    
    # assume 'selected_tags' contains tags to be filtered
    ordered_products = Product.objects.filter(tags__in=selected_tags).annotate(num_tags=Count('tags')).order_by('-num_tags')