Django-Using distinct on a specific field with annotate

67 Views Asked by At

I have following models:

class Post(models.Model):
    title = models.CharField(max_length=30)

class PostView(models.Model):
    post = models.ForeignKey(Post, related_name='views', on_delete=models.CASCADE)
    user = models.ForeignKey(get_user_model(), related_name='my_views')
    created = models.DateTimeField(auto_now_add=True)

I want to get posts ordered by number of unique views. I get the posts ordered by views by following code:

filters = {
    'created__date__gte': datetime.datetime(year=2020, month=1, day=1),
    'created__date__lte': datetime.datetime(year=2021, month=1, day=1),
}

qs = Post.objects.all().annotate(
    total_views=Count('views', filter=Q(**filters))
).order_by('-total_views')

above code will calculate all views as total_views. I want to get unique views by user. Is it possible to do that with ORM?

1

There are 1 best solutions below

1
On BEST ANSWER

Instead of counting views, you can count views__user directly and apply a distinct=True on this aggregation:

qs = Post.objects.all().annotate(
    total_views=Count('views__user', distinct=True, filter=Q(**filters))
).order_by('-total_views')