Python 如何在django中从多对多中间模型中进行选择?
我有书和人的模型:Python 如何在django中从多对多中间模型中进行选择?,python,django,django-models,Python,Django,Django Models,我有书和人的模型: 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,我会在中间表上进行选择,并将其与people表
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,我会在中间表上进行选择,并将其与people表连接以获得名称,但我不确定如何在此处执行类似操作。。。当然,Person表中有些人不是图书作者,或者我可以通过以下方法轻松获取Person.objects.all()
出于好奇,我根据本主题中提出的每种方法生成了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>]
[9]中的:Person.objects.annotate(count\u book=count('book')).filter(count\u book\u gt=0)
调试(0.000)选择“testapp\u person”。“id”,“testapp\u person”。“name”,计数(“testapp\u book\u author”。“book\u id”)作为“COUNT\u book”,从“testapp\u person”左侧外部加入“testapp\u book\u author”上的“testapp\u person”。“id”=“testapp\u book\u author”。“person”;“id”,“testapp\u person”。“person”;“姓名”,“testapp\u person”。“姓名”计数(“测试书作者”,“书id”)>0限制21;args=(0,)
出[9]:[]
在[10]中:Person.objects.exclude(book=None)
DEBUG(0.000)从“testapp_person”中选择“testapp_person”。“id”,“testapp_person”。“name”从“testapp_person”中选择(从“testapp_person”中选择U0。“id”从“testapp_person”中选择U0。“id”从“testapp_person”中选择“id”。“name”从“testapp_person”中选择(U0.“id”=U1.“person”从(U1.“book_id”=U2.“id”)从(U2.)和“遗嘱人”。“id”不为空)限制21;args=()
出[10]:[]
[11]中:Person.objects.filter(pk\u In=Book.objects.values\u list('author').distinct())
调试(0.000)从“testapp_人”中选择“testapp_人”。“id”,“testapp_人”。“名称”,其中“testapp_人”。“id”位于(从“testapp_书”中选择不同的U1。“person_id”位于“testapp_书”U0左侧外部连接“testapp_书作者”U1 ON(U0.“id”=U1.“book_id”))限制21;args=()
Out[11]:[]
也许这能帮你选择
我个人更喜欢克里斯的版本,因为它是最短的。另一方面,我不确定子查询的影响,其他两种方法也是如此。也就是说,它们确实展示了相互测试的QuerySet概念:
person.objects.annotate(count\u book=count('book')).filter(count\u book\u gt=0)[0]。count\u book
django书的这一章用与您非常相似的示例回答了您所有的模型需求,包括许多关系 您可以很容易地使用
Book.objects.all().values\u list('author',flat=True).distinct()
正如jpic在下面指出的那样
Person.objects.filter(pk\u in=Book.objects.values\u list('author').distinct())
将为您提供所有Person对象,而不仅仅是其id。最简单的方法:
Person.objects.filter(book__isnull=False)
这将选择至少有一本书与之关联的所有人。看起来像是此stackoverflow问题的重复。链接和文档侧重于获取
书
实例的所有人
;不仅仅是所有有书的人
,你能解释一下注释版本吗?当然,如果你有更具体的问题,请告诉我。我必须承认,一开始使用起来比理解起来容易,但是如果你把整个手册读几遍,你就会完全明白了!是的,我已经看过一次手册的大部分内容,并且再次点击了一些章节。很明显,我会多次返回!s/all/filter/在代码段中。这同样适用于:Person.objects.exclude(book=None)伟大的答案!是的。注意到在我看到你的评论之前。全脑放屁。不重复获得作者名单。我想这是在问题中暗示的,尽管我可能只是在想象。
Person.objects.filter(book__isnull=False)