Django аннотировать агрегацию подзапроса - PullRequest
2 голосов
/ 07 февраля 2020

Итак, у меня есть три модели

class Advert(BaseModel):
    company = models.ForeignKey(Company, on_delete=CASCADE, related_name="adverts")

class Company(BaseModel):
    name = models.CharField(max_length=50)

class OrderRating(BaseModel):
    reported_company = models.ForeignKey(Company, on_delete=CASCADE, related_name='ratings')
    rating = models.DecimalField(
        max_digits=2,
        decimal_places=1,
        validators=[MinValueValidator(1.0), MaxValueValidator(5.0)],
        help_text='Rating from 1.0 to 5.0.'
    )

И я пытаюсь получить среднее значение всех рейтингов заказов, связанных с компанией, и аннотировать это для модели Advert, когда я делаю это:

 qs = Advert.objects.all().annotate(
        avg_rating=Subquery(
            OrderRating.objects.filter(
               reported_company=OuterRef('company')).aggregate(Avg("rating"))["rating__avg"]
            )
        )

Я возвращаюсь, заявляя

This queryset contains a reference to an outer query and may only be used in a subquery.'

Не уверен, где проблема, когда я звоню на OuterRef внутри Subquery.

1 Ответ

2 голосов
/ 07 февраля 2020

Согласно моему опыту Subqueries часто немного хитры и плохо документированы. И они, как правило, возвращают сообщение, которое вы получаете, когда в вашем коде есть ошибка, определяющая подзапрос (на самом деле это не очень полезное сообщение).

Насколько я знаю, aggregate не работает в Subequeries, вместо этого вы должны использовать annotations. Так что это должно работать:

qs = Advert.objects.all().annotate(
        avg_rating=Subquery(
            OrderRating.objects.filter(
               reported_company=OuterRef('company')).values('reported_company').annotate(av=Avg('rating')).values('av')
            )
        )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...