#python #django #django-rest-framework
#python #django #django-rest-framework
Вопрос:
У меня есть 2 модели -> Кандидат и оценка. У 1 кандидата много оценок. Я хочу вернуть из rest API среднюю оценку из многих оценок, которые может получить один кандидат. Как я могу это сделать.
Моя модель:
class Candidate(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
class Grade(models.Model):
value = models.IntegerField(blank=True, null=True)
candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE, related_name='grades')
Мой serializers.py
from rest_framework import serializers
from .models import Candidate, Grade
class CandidateSerializer(serializers.ModelSerializer):
pk = serializers.SerializerMethodField('get_pk_from_candidate')
full_name = serializers.SerializerMethodField('get_full_name_from_candidate')
grades = serializers.SlugRelatedField(many=True, read_only=True, slug_field='value')
class Meta:
model = Candidate
fields = ['pk', 'full_name', 'avg_grade', 'grades']
def get_pk_from_candidate(self, candidate):
return candidate.id
def get_full_name_from_candidate(self, candidate):
data = (candidate.first_name, candidate.last_name)
full_name = ' '.join(data)
return full_name
Я хочу, чтобы мой формат JSON выглядел следующим образом:
{
"pk": 3,
"full_name": "rafał małek",
"avg_grade": "",
"grades": [
12,
4,
13,
5
]
},
Комментарии:
1. Я попытался написать метод, в котором я могу вычислить среднее значение, но я не знаю, как обрабатывать в этом методе массив моих оценок
Ответ №1:
Вы можете использовать SerializerMethodField() и агрегацию ORM (doc) с помощью Avg.
from django.db.models import Avg
from rest_framework import serializers
from .models import Candidate, Grade
class CandidateSerializer(serializers.ModelSerializer):
pk = serializers.SerializerMethodField('get_pk_from_candidate')
full_name = serializers.SerializerMethodField('get_full_name_from_candidate')
avg_grade = serializers.SerializerMethodField('get_avg_grade')
grades = serializers.SlugRelatedField(many=True, read_only=True, slug_field='value')
class Meta:
model = Candidate
fields = ['pk', 'full_name', 'avg_grade', 'grades']
def get_pk_from_candidate(self, candidate):
return candidate.id
def get_full_name_from_candidate(self, candidate):
data = (candidate.first_name, candidate.last_name)
full_name = ' '.join(data)
return full_name
def get_avg_grade(self, candidate):
return candidate.grades.aggregate(Avg('value'))['value__avg']
Ответ №2:
Использовать serializers.SerializerMethodField
как
from django.db.models import Avg
class CandidateSerializer(serializers.ModelSerializer):
pk = serializers.SerializerMethodField('get_pk_from_candidate')
full_name = serializers.SerializerMethodField('get_full_name_from_candidate')
grades = serializers.SlugRelatedField(many=True, read_only=True, slug_field='value')
avg_grade = serializers.SerializerMethodField()
def get_avg_grade(self, candidate):
return candidate.grades.aggregate(avg_value=Avg('value')).get("avg_value")
class Meta:
model = Candidate
fields = ['pk', 'full_name', 'avg_grade', 'grades']
def get_pk_from_candidate(self, candidate):
return candidate.id
def get_full_name_from_candidate(self, candidate):
data = (candidate.first_name, candidate.last_name)
full_name = ' '.join(data)
return full_name