Django filter model by it's related model list

Question:

There is purchase orders which contains n+1 products.
I want to filter PurchaseOrder by products in it.
In search process for looking up PurschaseOrders query set should return all purchase orders where there are itemA and itemB in it.

Modell classes

class PurchaseOrder:
    id = ....

class Product:
    purchase_order = models.ForeignKey(PurchaseOrder, related_name='product')

For lookup as input values I have list of Product id’s, for example lets take q = [1,3,5]

As result I need all Purchase orders, which contains product1, prodcut2, product3.

I have tried something like this, but it doesn’t return any result.

   q_objects = (Q(product__in=query[0]), Q(product__in=query[1]))
   qs = self.filter(q_objects)

As additional solution, which is not done in the code, because in opinion can cost a lot of resources:
1.return query of purchase orders, which contain product1.
Looping trough again, this time checking if Purchase orders contain product2, then keep for further validation. And keep the process with product all ids, from list.

  1. by using django signals, which on each save signal, saves all product id’s comma separated in text field. Which is compared with q

This currently is first level of implementation. Later it would be necessary to filter also by count.
For example if q =[1,1,3,5] will return all products, where there are two products1 and one for each product3 and product5.

Asked By: Uldis

||

Answers:

You can filter with:

from django.db.models import Count

ids = [1, 3, 5]
PurchaseOrder.objects.filter(product_id__in=qs).alias(
    nproducts=Count('product')
).filter(nproducts=len(set(ids)))
Answered By: Willem Van Onsem
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.