Вы обычно не сами рассчитываете агрегаты, но дайте базе данных сделать это. Базы данных оптимизированы для этого. Итерирование по коллекции приведет к тому, что базе данных потребуется передать все соответствующие записи, что приведет к использованию большой полосы пропускания.
Если вы хотите рассчитать средний рейтинг, вы можете просто агрегировать по review_set
с Avg
агрегат [Django-doc] , например:
from django.db.models import <b>Avg</b>
class Accelerator(models.Model):
@property
def average_rating(self):
return self.<b>review_set</b>.aggregate(
<b>average_rating=Avg('overall')</b>
)['average_rating']
Вышеприведенное не очень полезно, если вам нужно сделать это для большого набора Accelerator
с, поскольку это приведет к запросу за Accelerator
. Однако вы можете annotate(..)
[Django-doc] ваш Accelerator
класс, например, с Manager
[Django-doc]
from django.db.models import Avg
class AcceleratorManager(models.Manager):
def <b>get_queryset</b>(self):
return super().get_queryset().<b>annotate</b>(
_average_rating=Avg('review__overall')
)
Затем мы можем изменить класс Accelerator
, чтобы сначала посмотреть, вычислено ли значение аннотацией:
class Accelerator(models.Model):
objects = models.Manager()
<b>objects_with_rating = AcceleratorManager()</b>
@property
def average_rating(self):
try:
return self._average_rating
except AttributeError:
self._average_rating = result = self.<b>review_set</b>.aggregate(
average_rating=Avg('overal')
)['average_rating']
return result
Если затем мы получим, к примеру, Accelerator.objects_with_rating.filter(pk__lt=15)
, мы массово вычислим средний рейтинг этих Accelerator
с.
Сохранение среднего значения в базе данных, вероятно, не очень хорошая идея, поскольку оно включает дублирование данных , а синхронизация дублирования данных, как правило, является сложной проблемой.