【问题标题】:Django Many To Many intersection filteringDjango 多对多交集过滤
【发布时间】: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 多对多过滤??

【问题讨论】:

    标签: python django orm django-queryset


    【解决方案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 实际上可能不是作者对象的列表。我发布的代码是否以某种方式失败?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 2011-01-14
    • 2015-08-08
    • 2015-10-14
    • 1970-01-01
    • 2016-06-19
    • 2018-06-07
    相关资源
    最近更新 更多