Reputation: 1020
Ok, we have three tables: Order, Product and OrderProduct. I want to find what Orders has some products, and I written the following function:
def get_orders_with_products(products):
if len(products) < 1:
raise Exception("at least one product expected")
query = get_order_set_query(products[0])
if len(procducts > 1):
for product in products[1:]:
query = query & get_order_set_query(product)
return Order.objects.filter(query)
def get_order_set_query(product):
product_orders = OrderProduct.objects \
.values_list('order_id', flat=True)\
.filter(product=product)
return Q(id__in=set(product_orders))
This code would result in a sql query like the following:
select * from Orders
where id in [1, 2, 3]
and id in [2, 3, 4]
Is there any way to make Django's ORM write the following query?
select * from Orders
where id in (select order_id from OrderProduct where product_id = 1)
and id in (select order_id from OrderProduct where product_id = 2)
Any suggestions to do this better?
Upvotes: 0
Views: 667
Reputation: 5656
Yes.
from django.db.models import Q
queryset = Order.objects.filter(Q(order_id = [1, 2, 3]) & Q(order_id = [2, 3, 4]))
You could replace the lists with something like
[id[0] for id in OrderProduct.objects.filter(product_id = 1).values_list('id')]
Alan
Upvotes: 0