Filter object and order by number of filters matched

Question:

I have the objects

>>> Post.objects.create(name='First post', tags=['tutorial', 'django', 'example'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['thoughts', 'django', 'example'])

I want to filter the Post objects to match a series of tags:

>>> filtered = Post.objects.filter(tags__in=['thoughts', 'django', 'example'])

Is there a way to order these results by the number of filters they matched?

Wanted result:

>>> filtered[0]
<Post: Third post>
>>> filtered[1] 
<Post: First post>
>>> filtered[2] 
<Post: Second post>

Actual result:

>>> filtered[0]
<Post: First post>
>>> filtered[1] 
<Post: Second post>
>>> filtered[2] 
<Post: Third post>

I’m using Django 3.2.14

Asked By: Yoltic Cruz Tello

||

Answers:

You can annotate with the number of filtered Tag objects:

from django.db.models import Count

filtered = Post.objects.filter(
    tags__in=['thoughts', 'django', 'example']
).alias(
    ntags=Count('tags')
).order_by('-ntags')
Answered By: Willem Van Onsem
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.