Выбор первого элемента в подзапросе отношения "многие ко многим" в django
Рассмотрите возможность иметь модель Book
со многими Comment
(из разных User
), которые могут принадлежать многим Categories
.
class Category(Model):
title = CharField(max_length=200)
class Book(Model):
title = CharField(max_length=200)
categories = ManyToManyField(Category)
class User(Model):
name = CharField(max_length=200)
class Comment(Book):
content = TextField()
book = ForeignKey(Book, null=False, on_delete=CASCADE)
user = ForeignKey(User, null=False, on_delete=CASCADE)
Я хочу выбрать комментарии для определенного Book
, и для каждого Comment
аннотировать его количеством комментариев, которые автор этого Comment
написал для первого Category
этой книги. И я хочу получить это в одном запросе. Что-то вроде этого:
def get_commnets(book):
main_category = book.categories.first()
n_same_comments_subquery = Subquery(
Comments.objects
.filter(user__id=OuterRef('user_id'), book__category__first=main_category)
.annotate(count=Count('pk'))
.values('count')
)[:1]
comments = (
book.comment_set
.annotate(n_same_comments=n_same_comments_subquery)
)
return comments
Предыдущий кусок кода, очевидно, не работает. Это происходит потому, что нет никакого поиска, как first
. Я пробовал много других решений, но ни одно из них не сработало.
Как я могу достичь этой цели?
Заранее спасибо.
Хитрость заключалась в использовании through
:
def get_commnets(book):
main_category_id = book.categories.first().id
n_same_comments_subquery = Subquery(
Comments.objects
.alias(first_book_category_id=Book.categories.through.objects.filter(book_id=OuterRef('book_id')).values('id')[:1])
.filter(user__id=OuterRef('user_id'), first_book_category_id=main_category_id)
.annotate(count=Count('pk'))
.values('count')[:1]
)
comments = (
book.comment_set
.annotate(n_same_comments=n_same_comments_subquery)
)
return comments