Thursday, May 12, 2016

selecting an item whose relations are all in some desired set

Django is missing the "not in" operator and I have a situation where the workarounds (using ~Q or using exclude) don't seem to give a satisfactory solution.

Suppose I have two models:

from django.db.models import Model, ForeignKey
class Bundle(Model):
  pass

class Item(Model):
  bundle = ForeignKey(Bundle, related_name="items")


Suppose special_items is a list of Items and I want to select a bundle whose items are all in special_items, and I would like to use only 1 DB query.  The most natural way to do this would be Bundle.objects.filter(items__not_in=special_items), except that Django doesn't have a not_in lookup.

The following doesn't work:
Bundle.objects.filter(items__in=special_items)
because it will select Bundles where there exists a related item in special_items, but it will also select bundles that have items not in special_items.

I couldn't find a good way to use ~Q() and exclude to achieve this.  The problem is that a query on the related field is a "there exists" statement, and what I need is a "there exists a related item that is not in special_items", whereas the only ways I could come up with using ~Q() and exclude will end up giving statements of the form "all related items are not in special_items".

Am I missing an easy solution for this?  (Again only interested in solutions using a single query.)

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/35f1e364-28ea-4d26-bca5-6a265758430c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment