Как, например, использовать _set в SerializerMethod?
Я хочу вычислить средний рейтинг с помощью SerializerMethodField(). Ошибка в следующем коде AttributeError: 'FeedbackModel' object has no attribute 'aggregate'
Я думаю, что _set отсутствует, но я не знаю, куда его вставить...
class FeedbackSerializer(serializers.ModelSerializer):
feedback_by_user_profile_pic = serializers.ImageField(source='feedback_by.profile_pic')
average_rating = serializers.SerializerMethodField()
def get_average_rating(self,instance):
return instance.aggregate(average_rating=Avg('rating'))['average_rating']
class Meta:
model = FeedbackModel
fields = ['feedback_text','rating','date','feedback_by_user_profile_pic','average_rating']
Модель обратной связи
class FeedbackModel(models.Model):
feedback_text = models.CharField(max_length=1000)
rating = models.IntegerField()
date = models.DateField(auto_now=True)
feedback_by = models.ForeignKey(UserModel,on_delete=models.CASCADE)
business_account = models.ForeignKey(BusinessAccountModel,on_delete=models.CASCADE)
class Meta:
db_table = 'feedback'
Я думаю, что вам нужно добавить поле average_rating
в BusiAccSerializer
, а не в FeedbackSerializer
.
Сначала вам нужно установить атрибут related_name
в FeedbackModel
.
class FeedbackModel(models.Model):
...
# here I added the `related_name` attribute
business_account = models.ForeignKey(BusinessAccountModel,on_delete=models.CASCADE, related_name="feedbacks")
А затем в BusiAccSerializer
,
class BusiAccSerializer(serializers.ModelSerializer):
average_rating = serializers.SerializerMethodField(read_only = True)
def get_average_rating(self, obj):
return obj.feedbacks.aggregate(average_rating = Avg('rating'))['average_rating']
class Meta:
model = BusinessAccountModel
fields = (
'business_title', 'business_description', 'status', 'note', 'user', 'average_rating',
)
Прежде всего, вы указали, что вам нужен средний рейтинг для бизнес-счета, но вы не можете получить средний рейтинг для счета, не имея конкретного бизнес-счета, поэтому вам нужно сделать это в сериализаторе бизнес-счетов.
Дэвид Лу уже ответил, как это сделать в BusiAccSerializer, но у меня есть что добавить: То, что вы пытаетесь сделать, это использовать поле метода сериализатора для добавления некоторых агрегированных данных на выходе. Этот способ решения вашей проблемы имеет существенный недостаток: когда вы попытаетесь сериализовать список BusinessAccountModels, сериализатор будет делать отдельный вызов базы данных для каждого бизнес-счета, и это может быть медленным. Лучше указать аннотированный кверисет в представлении следующим образом:
BusinessAccountModel.objects.all().annotate(average_rating=Avg('feedbacks__rating'))
Тогда вы сможете использовать результат вычисления как обычное поле в вашем сериализаторе:
class BusiAccSerializer(serializers.ModelSerializer):
...
average_rating = serializers.FloatField(read_only=True)
Таким образом, сериализатор не будет выполнять дополнительных запросов к базе данных.