NotImplementedError Джанго: агрегат () + отчетливые (поля) не реализованы - PullRequest
2 голосов
/ 23 апреля 2019

У меня довольно простые модели:

class Profile(models.Model):
    name = models.CharField(max_length=100, unique=True)
    age = models.IntegerField(default=18)


class Place(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)
    address = models.CharField(max_length=100, blank=True, null=True)


class ProfilePlaceFeedback(models.Model):
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='feedback_set')
    place = models.ForeignKey(Place, on_delete=models.CASCADE, related_name='feedback_set')
    review = models.TextField(blank=True, null=True)
    rating = models.IntegerField(default=0)
    timestamp = models.DateTimeField(auto_now_add=True)

ProfilePlaceFeedback - модель для хранения каждого рейтинга, оставленного пользователем. И чтобы подсчитать рейтинг для некоторого place, мне нужно получить все ПОСЛЕДНИЕ отзывы пользователей и суммировать все значения рейтинга. Вот код для получения всех последних отзывов каждого пользователя:

place.feedback_set.order_by('profile', '-timestamp').distinct('profile')

Но сделав запрос:

place.feedback_set.order_by('profile', '-timestamp').distinct('profile').aggregate(Sum(rating))

Возникает исключение:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/PATH_TO_VIRTUALENV/lib/python3.6/site-packages/django/db/models/query.py", line 357, in aggregate
    raise NotImplementedError("aggregate() + distinct(fields) not implemented.")
NotImplementedError: aggregate() + distinct(fields) not implemented.

Использование Django 2.0 и postgresql в качестве базы данных.

Пожалуйста, помогите мне с этой проблемой:)

Ответы [ 2 ]

0 голосов
/ 24 апреля 2019

Кажется, вам нужно это или что-то подобное:

place.feedback_set.values('profile').annotate(rating_sum=Sum(rating)).values('profile','rating_sum').order_by('profile')
0 голосов
/ 23 апреля 2019

Полагаю, вы ищете сводные данные, например:

from django.db.models import F

Profile
.objects
.values(profile_name=F('name'),            
        place_name=F('profileplacefeedback__place__name'),
        )
.annotate(timestamp=Max('profileplacefeedback__timestamp'),
          rating=Sum('profileplacefeedback__rating'))
.order_by( 'profile_name', '-timestamp')

Если вам нужно больше данных, просто добавьте их в раздел values.

Отказ от ответственности: запросздесь не проверял, просто написал от руки.Сообщите мне, если это не удастся исправить или удалить ответ (чтобы помочь будущим пользователям)

Отредактировано После OP Комментарий:

Мне нужно рассчитать средний рейтинг для данного места и отфильтровать только последний рейтинг, оставленный профилем.

Вы ищете FirstValue из оконные функции django ,

from django.db.models import Avg,  F, RowRange, Window
from django.db.models.functions.window import FirstValue

q=( Place
   .objects
   .annotate(
        avg_rating=Window(
            expression=FirstValue('feedback_set__rating'),
            partition_by=[F('feedback_set__profile'),
                          F('feedback_set__place')],
            order_by=F('feedback_set__timestamp').desc()
        )
     )
    .values(
        place_name=F('feedback_set__place__name'),
     )
    .annotate(
        rating=Avg('avg_rating')
     )
)

Базовый SQL:

>>> print (q.query)

SELECT
   T4."name" AS "place_name",
   AVG(FIRST_VALUE("a_profileplacefeedback"."rating") 
       OVER (PARTITION BY "a_profileplacefeedback"."profile_id", 
                          "a_profileplacefeedback"."place_id" 
             ORDER BY "a_profileplacefeedback"."timestamp" DESC)) AS "rating" 
FROM
   "a_place" 
   LEFT OUTER JOIN
      "a_profileplacefeedback" 
      ON ("a_place"."id" = "a_profileplacefeedback"."place_id") 
   LEFT OUTER JOIN
      "a_place" T4 
      ON ("a_profileplacefeedback"."place_id" = T4."id") 
GROUP BY
   T4."name"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...