About Finding Items Similar to a Reference Item

You can find posts similar to a reference post by counting the matching facts about those posts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from django.db import models
from posts.models import Post

reference_post = Post.objects.first()

for post in Post.objects.annotate(
    matching_categories=models.Count(
        "categories",
        distinct=True,
        filter=models.Q(categories__in=reference_post.categories.all()),
    ),
    matching_tags=models.Count(
        "tags",
        distinct=True,
        filter=models.Q(tags__in=reference_post.tags.all()),
    ),
    matching_post_type=models.Count(
        "post_type",
        distinct=True,
        filter=models.Q(post_type=reference_post.post_type),
    ),
    matching_score=models.ExpressionWrapper(
        models.F("matching_categories")
        + models.F("matching_tags")
        + models.F("matching_post_type"),
        output_field=models.PositiveIntegerField(default=0),
    ),
).exclude(pk=reference_post.pk).order_by("-matching_score"):
    print(post, post.matching_score)

Tips and Tricks Programming Development Databases Django 5.x Django 4.2 Django 3.2