如何进行多对多 Django 查询来查找具有 2 个给定作者的书籍?
我有一个查询,要求使用 ID 精确过滤 2 位作者
,理论上
Book.objects.filter(author__id=1, author__id=2).
这是不可能的。
我该如何解决这个问题?
干杯, 米奇
I have a query that requires to filter exactly 2 authors with the ID
Theoretically,
Book.objects.filter(author__id=1, author__id=2).
which is not possible.
How can I solve this problem?
Cheers,
Mickey
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
一开始并不直观,但答案就在我们面前。
如果您想要完全匹配,您可以通过那些只有 2 位作者的项目进一步过滤此结果。
如果你想要动态精确匹配,像这样怎么样?:
Not intuitive at first but the answer is right in front of us.
If you want an exact match, you could potentially further filter this result by those items that only have exactly 2 authors.
If you want exact matches dynamically, how about something like this?:
新问题指向此问题重复,因此这里是更新的答案(针对一个特定后端)。
如果后端是 Postgres,您想要的 SQL 是(假设 M2M 表名为
bookauthor
):您可以让 Django 生成几乎这个 SQL。
首先,
pip install django-sql-utils
。然后创建这个 Array 类:现在您可以编写 ORM 查询集:
New questions are pointing to this one as a duplicate, so here is an updated answer (for one specific backend).
If the backend is Postgres, the SQL you want is (assuming the M2M table is called
bookauthor
):You can get Django to generate nearly this SQL.
First,
pip install django-sql-utils
. Then create thisArray
class:And now you can write your ORM queryset:
使用 Postgres 作为数据库时,您可以使用 ArrayAgg 来收集数组中的作者 ID,然后按该数组进行过滤:
我使用了
distinct
和ordering< /code> 以确保 ID 不会重复并且始终保持相同的顺序。
此解决方案在生成的 SQL 中仅生成一个
JOIN
,而链接多个.filter()
方法会在查询中生成多个JOIN
。When using Postgres as a database, you could use
ArrayAgg
to collect author IDs in an array and then filter by that array:I've used
distinct
andordering
to make sure that IDs will have no duplicates and will always be in the same order.This solution produces only one
JOIN
in the resulting SQL, whereas chaining several.filter()
methods produces severalJOIN
s in the query.Q 对象会帮助你。 文档< /a>
Q objects will help you. Docs
您可以使用“IN”查询。
Django 文档
Book.objects.filter(author__id__in =[1,2])
You can use an "IN" query.
Django Docs
Book.objects.filter(author__id__in=[1,2])