Django - Какой самый эффективный способ запросить средние оценки для списка объектов? - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть простой класс Product and Rating, например:

class Product(models.Model):
   name = ...
   price = ...

class Rating(models.Model):
   product = models.ForeignKey("Product", ...)
   score = models.PositiveSmallIntegerField(...)

Теперь я хочу получить список всех товаров и средний рейтинг для каждого товара.Просто получить все продукты просто:

product_list = Product.objects.all()

Если у меня есть один продукт, и я хочу получить среднюю оценку для этого продукта:

product = get_object_or_404(Product, pk=product_id)
ratings = Rating.objects.filter(product=product)
product_avg_rating = ratings.aggregate((Avg("score")))

Но давайте предположим, что я хочуперечислите все продукты и их средний рейтинг.Это звучит так, как будто это довольно сложный ресурс.Так каков наилучший способ решить эту проблему?Должен ли я создать метод класса для класса Product, который просто возвращает среднее значение, чтобы я мог затем вызвать его в шаблоне:

{{ product.get_average_rating }}

Или есть лучший способ сделать это?Я не совсем уверен, что делать здесь, и мне нужно какое-то руководство.

Заранее большое спасибо!

РЕДАКТИРОВАТЬ: я думаю, что я не достаточно ясно с моим объяснением, так что вотфактический пример.Допустим, у меня есть набор запросов, отфильтрованный слагом (который является просто поисковым термином):

products = Product.objects.filter(tags__name__in=[slug])

Теперь, как я могу добавить средний рейтинг к КАЖДОМУ ОДНОМУ продукту, чтобы я мог сделать это в шаблоне:

{% for product in products %}
   {{ product.avg_rating_score }}
{% endfor %}

1 Ответ

0 голосов
/ 13 февраля 2019

Вы можете аннотировать ваш Product в первом запросе, так что для получения среднего значения потребуется только один запрос, например:

product = get_object_or_404(
    Product.object.<b>annotate(avg_score=Avg('rating__score'))</b>,
    pk=product_id
)

Это приведет кsingle Product, который содержит дополнительный атрибут (только для this specific QuerySet!), в шаблоне, таким образом, мы можем отобразить его следующим образом:

{{ product.<b>avg_score</b> }}

Запрос, который онделает это:

SELECT product.*, <b>AVG(rating.score) AS avg_score</b>
FROM product
LEFT OUTER JOIN rating ON product.id = rating.product_id
WHERE product.id = <i>product_id</i>
...