Django запрос для возврата процента пользователей, имеющих сообщение

Две модели Пользователи (встроенные) и Посты:

class Post(models.Model):
    post_date = models.DateTimeField(default=timezone.now)
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name='user_post')
    post = models.CharField(max_length=100)

Я хочу иметь конечную точку API, которая возвращает процент пользователей, разместивших сообщение. В основном мне нужно SUM(уникальные пользователи, которые разместили сообщение) / total_users

Я пытался играть с annotate и aggregate, но я получаю сумму постов для каждого пользователя или сумму пользователей на пост (который один...). Как я могу получить сумму постов, возвращенных уникальными пользователями, разделить ее на user.count и вернуть?

Мне кажется, что я упускаю что-то глупое, но мой мозг превратился в кашу, глядя на это.

class PostParticipationAPIView(generics.ListAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
            
    def get_queryset(self):
        start_date = self.request.query_params.get('start_date')
        end_date = self.request.query_params.get('end_date')
        # How can I take something like this, divide it by User.objects.all().count() * 100, and assign it to something to return as the queryset?
        queryset = Post.objects.filter(post_date__gte=start_date, post_date__lte=end_date).distinct('user').count()         
        return queryset

Моя цель состоит в том, чтобы в итоге получить конечную точку следующего вида:

{ общее_участие: 97.3 }

Спасибо за любое руководство.

BCBB

что-то вроде этого должно работать

# get total user count
total_users = User.objects.count()
# get unique set of users with post
total_users_who_posted = Post.objects.filter(...).distinct("user").count()
# calculate_percentage
percentage = { 
    "total_participation": (total_users_who_posted*100)/ total_users
}
# take caution of divion by zero

Я не думаю, что возможно использовать djangos orm для этого полностью, но вы можете использовать orm для получения количества пользователей (с постами и общим количеством):

from django.db.models import BooleanField, Case, Count, When, Value

counts = (User
          .objects
          .annotate(posted=Case(When(user_post__isnull=False,
                                     then=Value(True)),
                                default=Value(False), 
                                output_field=BooleanField()))
          .values('posted')
          .aggregate(posted_users=Count('pk', filter=Q(posted=True)),
                     total_users=Count('pk', filter=Q(posted__isnull=False)))

# This will result in a dict containing the following:
# counts = {'posted_users': ...,
#           'total_users': ....}
Вернуться на верх