Python 筛选满足一组条件的多对多关系

Python 筛选满足一组条件的多对多关系,python,django,many-to-many,django-orm,Python,Django,Many To Many,Django Orm,使用以下型号: class OrderOperation(models.Model): ordered_articles = models.ManyToManyField(Article, through='orders.OrderedArticle') class OrderedArticle(models.Model): order_operation = models.Foreig

使用以下型号:

class OrderOperation(models.Model):
    ordered_articles = models.ManyToManyField(Article,
                                              through='orders.OrderedArticle')

class OrderedArticle(models.Model):
    order_operation = models.ForeignKey(OrderOperation)
    article = models.ForeignKey(Article)
文章=。。。包含多个项目的某些queryset

如果我想查找至少包含一个项目的订单操作,这将按预期工作:

OrderOperation.objects.filter(ordered_articles__in=articles)
但是,如果我想找到订单中所有项目的订单操作,正确的方法是什么

OrderOperation.objects.filterordered_articles=articles引发编程错误:子查询返回的多行用作表达式错误我理解实际原因。

我们可以首先构造一组文章:

articles_set = set(articles)
由于在ManyToManyField中,每个项目可以在每个OrderOperation中出现一次,因此,如果项目集合中的相关项目数与项目集合中的元素数相同,则我们知道这两个集合是相同的

这将创建一个如下所示的查询:

SELECT orderoperation.*
       COUNT(orderoperation_article.article_id) AS narticle
FROM orderoperation
JOIN orderoperation_article ON orderoperation_id = orderoperation.id
WHERE orderoperation.article_id IN (article_set)
GROUP BY orderoperation.id
HAVING COUNT(orderoperation_article.article_id) = len(article_set)
其中article_集和lenarticle_集当然由集合中项目的主键或该集合中的元素数替换。

我们可以首先构造一组项目:

articles_set = set(articles)
由于在ManyToManyField中,每个项目可以在每个OrderOperation中出现一次,因此,如果项目集合中的相关项目数与项目集合中的元素数相同,则我们知道这两个集合是相同的

这将创建一个如下所示的查询:

SELECT orderoperation.*
       COUNT(orderoperation_article.article_id) AS narticle
FROM orderoperation
JOIN orderoperation_article ON orderoperation_id = orderoperation.id
WHERE orderoperation.article_id IN (article_set)
GROUP BY orderoperation.id
HAVING COUNT(orderoperation_article.article_id) = len(article_set)
其中article_集和lenarticle_集当然由集合中项目的主键或集合中元素的数量替换。

一个简单的解决方案:

order_operations = OrderOperation.objects.all()
for article in articles:
    order_operations = order_operations.filter(ordered_articles=article)
这只是一个查询,但每篇文章都有一个内部联接。对于不止几篇文章,Willem更巧妙的解决方案应该表现得更好。

一个简单的解决方案:

order_operations = OrderOperation.objects.all()
for article in articles:
    order_operations = order_operations.filter(ordered_articles=article)

这只是一个查询,但每篇文章都有一个内部联接。对于不止几篇文章,Willem更巧妙的解决方案应该表现得更好。

Hi:看来filterordered\u articles\uuuu in=articles\u set与filterordered\u articles\uu in=articles具有完全相同的效果。在这两种情况下,它都会过滤至少包含1个项目的订单操作。@david:是的,这是正确的,我们在相关集合上进行过滤,点不是过滤,然后我们应该。注释。。满足该条件的文章数量,然后根据该数量进行筛选,因此.annotate…筛选。。部分最终成功了。非常感谢,这很有效!不幸的是,我无法使用您的解决方案,因为我在使用子查询时过度简化了我的问题。我可以请你看一看吗?非常感谢。您好:似乎filterordered\u articles\u in=articles\u set与filterordered\u articles\u in=articles具有完全相同的效果。在这两种情况下,它都会过滤至少包含1个项目的订单操作。@david:是的,这是正确的,我们在相关集合上进行过滤,点不是过滤,然后我们应该。注释。。满足该条件的文章数量,然后根据该数量进行筛选,因此.annotate…筛选。。部分最终成功了。非常感谢,这很有效!不幸的是,我无法使用您的解决方案,因为我在使用子查询时过度简化了我的问题。我可以请你看一看吗?非常感谢,谢谢!我把这个作为公认的答案,因为它更容易阅读,当有几篇文章时,我会表现得很好,就像你说的:谢谢!我将此作为公认的答案,因为它更易于阅读,当有几篇文章时,ans执行正常,正如您所说: