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, каждый из которых аннотирован пк самой дешевой книги, которую он продает.
Пожалуйста, скажите мне, правильно ли я это понял!