首页 > 解决方案 > 通过多对多字段使用来自另一个模型的查询集过滤方法注释子查询

问题描述

我不确定如何使这成为可能,但我希望了解执行以下操作的预期方法:

我有一个简单的模型:

class Author(models.Model):
    id = models.TextField(primary_key=True, default=uuid4)
    name = models.TextField()
    main_titles = models.ManyToManyField(
        "Book",
        through="BookMainAuthor",
        related_name="main_authors",
    )

    objects = AuthorManager.from_queryset(AuthorQuerySet)()


class Book(models.Model):
    id = models.TextField(primary_key=True, default=uuid4)
    title = models.TextField()
    genre = models.ForeignKey("Genre", on_delete=models.CASCADE)
    
    objects = BookManager.from_queryset(BookQuerySet)()


class BookQuerySet(QuerySet):
    def by_genre_scifi(self) -> QuerySet:
        return self.filter(**self.LOOKUP_POPULAR_SCIFI)

我想添加一个新的 QuerySet 方法来使用上面的方法AuthorQuerySet来注释Author对象BookQuerySet。我试过以下,这是不正确的:

class AuthorQuerySet(QuerySet):
    def annotate_with_total_titles_by_genres(self) -> QuerySet:
        main_titles_by_genre_sci_fi_query = Book.objects.filter(main_authors__in=[OuterRef('pk')]).all()
            .by_genre_sci_fi()
            .annotate(cnt=Count('*'))
            .values('cnt')[:1]

        return self.annotate(sci_fi_titles_total = 
             Subquery(main_titles_by_genre_sci_fi_query, output_field=IntegerField()))

预期用途:

annotated_authors = Author.objects.filter(<some filter>).annotate_with_total_titles_by_genres()

上面的模型中没有显示查找中的其他字段,但是这里的方法是有效的,并返回BookQuerySet由查找过滤的:

Book.objects.filter(main_authors__in=['some_author_id']).all().by_genre_sci_fi()

同样,我可以独立运行子查询并获得如下计数:

`Book.objects.filter(main_authors__in=['some_author_id']).all()
            .by_genre_sci_fi()
            .annotate(cnt=Count('*'))
            .values('cnt')[:1]`
Out[1]: <BookQuerySet [{'cnt': 1}]>

但是,当我尝试使用上面的 AuthorQuerySet 方法进行注释时,我会得到None每个条目。

我想知道这里是否存在问题,OuterRef如果in它接收到一个字符串,它将独立评估每个字符。如果我尝试在没有方括号的情况下运行它:

ProgrammingError: syntax error at or near ""bookshop_author"" LINE 1: ...RE (U0."deleted_at" IS NULL AND U1."author_id" IN "bookshop_...

标签: pythondjangodjango-modelsdjango-queryset

解决方案


推荐阅读