Django аннотирует значения модели

В Django docs on aggregation приводится следующий пример для аннотаций:

for store in Store.objects.all():
    store.min_price # Error! min_price not defined!
for store in Store.objects.annotate(min_price=Min('books__price')):
    store.min_price # Fine

Однако мы аннотировали только одно поле. Мы знаем только цену самой дешевой книги, но не точную цену самой дешевой книги . Что если я хочу, чтобы результатом аннотации была именно эта книга, а не просто ее цена? (Я назову эту функцию или класс )AggregateRelation

for store in Store.objects.annotate(
   cheapest_book=AggregateRelation('books__price', Min)
):
    store.cheapest_book.price
    store.cheapest_book.title

Есть ли способ сделать это?

Я проверил FilteredRelation, но это полезно только для фильтрации. Он не позволяет действительно получить экземпляры.

Если (и только если) вы используете PostgreSQL, то я думаю, что есть ответ, используя .distinct(fields)

Book.objects.order_by('store_id', 'price').distinct('store_id')

должен получить самую дешевую книгу для каждого магазина, если я правильно понял документацию (ссылка выше). Добавление select_related() должно означать, что вы не будете снова обращаться к БД, когда ссылаетесь на book.store.whatever

Если у вас нет PostgreSQL, я думаю, вы можете использовать SubQuery. Ниже приведена моя попытка следовать документации:

from django.db.models import OuterRef, Subquery

cheapest = Book.objects.filter(store=OuterRef('pk')).order_by('price')
stores = Store.objects.annotate(cheapest_book_pk=Subquery(cheapest.values('pk')[:1]))

После этого вы получите список объектов Store, каждый из которых аннотирован пк самой дешевой книги, которую он продает.

Пожалуйста, скажите мне, правильно ли я это понял!

Вернуться на верх