Хотим вернуть процент в Django Rest Framework

  • Я хотел вернуть процент каждого опроса options_data в ответ.
  • Я ожидаю результат, как показано ниже.
{
    "response": true,
    "return_code": "remove_vote_success",
    "result": {
        "id": 9,
        "user_id": 2,
        "question": "what would you like to see more of on our channel?",
        "created_on": "2022-09-06T05:52:39",
        "active": true,
        "options_data": [
            {
                "id": 25,
                "poll_id": 9,
                "option_text": "Video editing tutorials",
                "percentage_count": 50.0
            },
            {
                "id": 26,
                "poll_id": 9,
                "option_text": "Clipchamp product updates",
                "percentage_count": 10.0
            },
            {
                "id": 27,
                "poll_id": 9,
                "option_text": "Social media growth tips"
                "percentage_count": 40.0
            },
            {
                "id": 28,
                "poll_id": 9,
                "option_text": "Clipchamp tips and tricks",
                "percentage_count": 0.0
            }
        ]
    },
    "message": "Vote get successfully."
}
  • это мой models.py
class Polls(models.Model):
    user = models.ForeignKey(User, related_name="polls_data", on_delete=models.CASCADE)
    question = models.TextField(max_length=250, blank=False, null=False)
    created_on = models.DateTimeField(default=timezone.now)
    active = models.BooleanField(default=True)


class Options(models.Model):
    poll = models.ForeignKey(Polls, related_name="options_data", on_delete=models.CASCADE)
    option_text = models.CharField(max_length=255)


class Vote(models.Model):
    user = models.ForeignKey(User, related_name="vote_data", on_delete=models.CASCADE)
    poll = models.ForeignKey(Polls, on_delete=models.CASCADE)
    option = models.ForeignKey(Options, on_delete=models.CASCADE)
  • это мой serializer.py
class OptionsSerializer(serializers.ModelSerializer):

    class Meta:
        model = Options
        fields = ('id', 'poll_id', 'option_text')

class PollsSerializer(serializers.ModelSerializer):
    
    options_data = OptionsSerializer(many=True, read_only=True)

    class Meta:
        model = Polls
        fields = ('id','user_id', 'question', 'created_on', 'active',  'options_data')

В вашем OptionsSerializer добавьте поле, которое берет .count() из рассматриваемого варианта и делит на count() из всех ответов на этот вопрос. (затем умножьте это на 100, чтобы получить процент)

class OptionsSerializer(serializers.ModelSerializer):
    percentage_count = serializers.SerializerMethodField()

    ...

    def get_percentage_count(self, obj): 
       total_votes = Vote.objects.filter(poll=obj.poll).count()
       share_of_votes = Vote.objects.filter(option=obj).count()
       return Decimal(
           (share_of_answers / total) * 100
       ).quantize(Decimal('.01'))

если мы возвращаем значения непосредственно в ответ, то, возможно, вы столкнетесь с ZeroDivisionError. Поэтому для эффективности кода используйте это.

class OptionsSerializer(serializers.ModelSerializer):

    percentage_count = serializers.SerializerMethodField()

    class Meta:
        model = Options
        fields = ('id', 'poll_id', 'option_text', 'percentage_count')

    def get_percentage_count(self, obj): 
       total_votes = Vote.objects.filter(poll_id=obj.poll).count()
       share_of_votes = Vote.objects.filter(option_id=obj).count()
       try:
            percentage = Decimal((share_of_votes / total_votes) * 100).quantize(Decimal('.01'))
       except ZeroDivisionError:
            return 0 
       return percentage

class PollsSerializer(serializers.ModelSerializer):
    
    options_data = OptionsSerializer(many=True, read_only=True)

    class Meta:
        model = Polls
        fields = ('id','user_id', 'question', 'created_on', 'active',  'options_data')
Вернуться на верх