With the following models:
class OrderOperation(models.Model):
ordered_articles = models.ManyToManyField(Article,
We can first construct a set
of articles:
articles_set = set(articles)
Next we can count the number of articles related to the OrderOperation
that appear in that set, and check if that number is equal to the size of that set, like:
from django.db.models import Count
OrderOperation.objects.filter(
ordered_articles__in=articles_set
).annotate(
narticles=Count('ordered_articles')
).filter(
narticles=len(articles_set)
)
Since in a ManyToManyField
, each Article
can occur once per OrderOperation
, if the number of related Article
s that are in the article_set
is the same as the number of elements in the article_set
, we thus know that the two sets are the same.
This will create a query that looks like:
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)
where the article_set
and len(article_set)
are of course replaced by the primary keys of the articles in the set, or the number of elements in that set.
A simple solution:
order_operations = OrderOperation.objects.all()
for article in articles:
order_operations = order_operations.filter(ordered_articles=article)
It's just one query, but with an inner join per article. For more than a few articles Willem’s more ingenious solution should perform better.