Django 多对多交集过滤
Posted
技术标签:
【中文标题】Django 多对多交集过滤【英文标题】:Django Many To Many intersection filtering 【发布时间】:2012-09-26 23:37:53 【问题描述】:为了简单起见,假设我只有 2 个模型:书籍、作者
class Author(models.Model):
name = models.CharField(max_length='100')
...
class Book(models.Model):
name = models.CharField(max_length='100')
authors = models.ManyToManyField(Author)
...
我想使用作者列表过滤图书。我试图做的是:
authors = [...] # a list of author objects
Books.objects.filter(authors__in=authors)
但是在这里,当我想要作者与作者时,他们会被 ORed。 有没有办法 AND 多对多过滤??
【问题讨论】:
【参考方案1】:你可以将一堆 Q 对象 & 在一起:
q = Q()
for author in authors:
q &= Q(authors=author)
Books.objects.filter(q)
要排除作者不在列表中的书籍,您可以将查询限制为与列表中作者数量完全相同的书籍:
Books.objects.annotate(count=Count('authors')).filter(count=len(authors)).filter(q)
更新:
基于 cmets,我认为要求是获取列表中至少一位作者撰写的所有书籍,但排除列表之外任何作者的书籍。
所以我们构建了一个查询集来选择我们讨厌的作者:
# this queryset will be embedded as a subquery in the next
bad_authors = Author.objects.exclude(name__in=['A1', 'A2'])
然后排除它们以找到我们想要的书籍:
# get all books without any of the bad_authors
Books.objects.exclude(authors__in=bad_authors)
这将返回所有书籍,但由您列表之外的人创作的书籍除外。如果您还想排除那些没有列出作者的人,请添加另一个排除调用:
Books.objects.exclude(authors__in=bad_authors).exclude(authors=None)
这将使我们只剩下一本或多本好书所写的书!
【讨论】:
还有一件事:我希望能够过滤仅包含列表中作者的书籍,没有额外的作者。你能帮我解决这个问题吗? @goliney 为什么这是错误的做法?请详细说明。 @dokkaebi 我又想了一遍,现在你的方法在我看来更正确。 +1 非常感谢@dokkaebi,太好了。但是我想我上一个问题有点不清楚,所以让我举个例子:authors = ['A1','A2'] @CodePirate 我认为与您的原始帖子相比,所有这些评论的变化是authors
实际上可能不是作者对象的列表。我发布的代码是否以某种方式失败?以上是关于Django 多对多交集过滤的主要内容,如果未能解决你的问题,请参考以下文章