Хотим вернуть процент в 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')