gpt4 book ai didi

python - 如何从 Django 中的多对多中间模型中进行选择?

转载 作者:行者123 更新时间:2023-11-28 21:28:17 25 4
gpt4 key购买 nike

我有书和人的模型:

from django.db import models

class Book(models.Model):
author = models.ManyToManyField('Person')

class Person(models.Model):
name = models.CharField(max_length=16)

我在这里对它们进行了一些简化。我如何制作一个 Django 查询来获取所有书籍的作者?使用 SQL 我会在中间表上进行选择并将其与人员表连接起来以获取名称,但我不确定如何在这里做类似的事情......当然,Person 表中的人是不是书的作者,或者我可以获得 Person.objects.all()。

最佳答案

使用 Filtering on annotations 就像 1,2,3 一样简单:

from django.db.models import Count

Person.objects.annotate(count_book=Count('book')).filter(count_book__gt=0)

出于好奇,我根据针对该主题提出的每种方法生成了 SQL:

In [9]: Person.objects.annotate(count_book=Count('book')).filter(count_book__gt=0)
DEBUG (0.000) SELECT "testapp_person"."id", "testapp_person"."name", COUNT("testapp_book_author"."book_id") AS "count_book" FROM "testapp_person" LEFT OUTER JOIN "testapp_book_author" ON ("testapp_person"."id" = "testapp_book_author"."person_id") GROUP BY "testapp_person"."id", "testapp_person"."name", "testapp_person"."id", "testapp_person"."name" HAVING COUNT("testapp_book_author"."book_id") > 0 LIMIT 21; args=(0,)
Out[9]: [<Person: Person object>]

In [10]: Person.objects.exclude(book=None)
DEBUG (0.000) SELECT "testapp_person"."id", "testapp_person"."name" FROM "testapp_person" WHERE NOT (("testapp_person"."id" IN (SELECT U0."id" FROM "testapp_person" U0 LEFT OUTER JOIN "testapp_book_author" U1 ON (U0."id" = U1."person_id") LEFT OUTER JOIN "testapp_book" U2 ON (U1."book_id" = U2."id") WHERE (U2."id" IS NULL AND U0."id" IS NOT NULL)) AND "testapp_person"."id" IS NOT NULL)) LIMIT 21; args=()
Out[10]: [<Person: Person object>]

In [11]: Person.objects.filter(pk__in=Book.objects.values_list('author').distinct())
DEBUG (0.000) SELECT "testapp_person"."id", "testapp_person"."name" FROM "testapp_person" WHERE "testapp_person"."id" IN (SELECT DISTINCT U1."person_id" FROM "testapp_book" U0 LEFT OUTER JOIN "testapp_book_author" U1 ON (U0."id" = U1."book_id")) LIMIT 21; args=()
Out[11]: [<Person: Person object>]

也许这可以帮助您做出选择。

就我个人而言,我更喜欢 Chris 的版​​本,因为它是最短的。另一方面,我不确定子查询对其他两种方式的影响。也就是说,它们确实展示了有趣的 QuerySet 概念:

  1. Annonation,是查询集每个值的聚合。如果您使用 aggregate(Count('book')) 那么您将获得书籍总数。如果您使用 annotate(Count('book')) ,那么您将获得每个查询集值(每个人)的书籍总数。此外,每个人都有一个“count_book”属性,这非常酷:Person.objects.annotate(count_book=Count('book')).filter(count_book__gt=0)[0] .count_book

  2. 子查询,对于创建复杂查询或优化查询(例如合并查询集、通用关系预取)非常有用。

关于python - 如何从 Django 中的多对多中间模型中进行选择?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8670389/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com