在django中的多对多关系的子查询中选择第一项
Selecting first item in a subquery of many to many relationship in django
考虑拥有一个 Book
模型,其中包含许多 Comment
s(来自不同的 User
s),这些模型可能属于许多 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)
我想 select 对特定 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
考虑拥有一个 Book
模型,其中包含许多 Comment
s(来自不同的 User
s),这些模型可能属于许多 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)
我想 select 对特定 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