Django filter on queryset intersection?

15,330

If you need your list of itemsets and you didn't get them from a query, try this:

itemset_list = [itemset1, itemset2, itemset3]
itemset_list_ids = [itemset.id for itemset in itemset_list]
itemset_queryset = ItemSet.objects.filter(id__in=itemset_list_ids)
items = Item.objects.filter(itemsets__in=itemset_queryset)

If you can get your itemset list by querying, that shortens it a little bit:

itemset_queryset = ItemSet.objects.filter(SOME FILTER HERE)
items = Item.objects.filter(itemsets__in=itemset_queryset)
Share:
15,330
Andrew
Author by

Andrew

Updated on June 04, 2022

Comments

  • Andrew
    Andrew almost 2 years
    class Item(models.Model):
        ...
    
    class ItemSet(models.Model):
        items = models.ManyToManyField(Item, related_name="itemsets")
    

    I have a list of ItemSets. I want to find all Item objects where the Item object is in the "items" M2M field on at least one of the ItemSet objects.

    How can I do this?

    P.S. Here is what I have tried, but to no avail:

    itemset_list = [itemset1, itemset2, itemset3]    
    items = Item.objects.filter(itemsets__in=itemset_list)
    
  • Cole
    Cole over 4 years
    In your second example, does Django make one or two queries to get the final items QuerySet?
  • 2ehr
    2ehr over 2 years
    @Cole it depends on what you do with the "items" variable. If you ask for some fields of "Item" model, Django will make only 1 query. But if you ask for any data external of the "Item" model (for example any data from "ItemSet" model) Django will make 1 query for the "Item" model and many queries for each "ItemSet" (or any other external model). To avoid it, you should include those models in a .select_related() or prefetch_related() queryset methods, depending on the relation between those models and "Item" model.