0

Lets say I have the following models setup:

class X(models.Model):
     ...

class Y(models.Model):
     x = models.ForeignKey(X)

class Z(models.Model):
     x = models.ForeignKey(X)

Now, in a method, I want to get all the Y objects and Z objects that are related to a given X object. I want to hit my database once, and return a combined queryset. Right now, I am doing it like this:

x = X.objects.get(pk=1)
queryset = []
for cls in [Y, Z]:
    queryset += list(cls.objects.filter(x=x))

Note: running it through a loop is important because there are quite a few models in my actual code, so looping keeps the whole thing DRY. How can I do this? Thanks.

darkhorse
  • 8,192
  • 21
  • 72
  • 148
  • @Pedro Could you please expand your comment into an answer with code examples using my model names? – darkhorse Apr 07 '19 at 22:06
  • 1
    my bad, you can't do ```select_related``` from a reverse foreign key. You can use ```prefetch_related```, but it will hit the database multiple times: https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related – p14z Apr 07 '19 at 22:26

1 Answers1

1

If you need to merge to querysets from different models, the best/fastest way is by using itertools. Keep in mind this converts it from a QuerySet to an ordinary List.

from itertools import chain
x = X.objects.get(pk=1)
y = Y.objects.filter(x=x)
z = Z.objects.filter(x=x)
result_list = list(chain(y, z))

As far as I know, there isn’t a way to query two different models that way, even with select_related or prefetch_related.

Hybrid
  • 6,741
  • 3
  • 25
  • 45