Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: How to get related objects of a queryset?

Assume I have two models:

A:
    pass

B:
    a = foreign_key(A)

Now, I have a query set

bs = B.objects.filter(...)

I want to get all the a of bs, which means every a which is referenced by b for which b is in bs.

Is there a way to do so? I think in sql, a simple join will do, I don't know if django support this.

like image 812
dspjm Avatar asked Mar 24 '16 09:03

dspjm


People also ask

What is annotate in Django QuerySet?

annotate() that has been computed over the objects that are related to the objects in the QuerySet . Each argument to annotate() is an annotation that will be added to each object in the QuerySet that is returned. The aggregation functions that are provided by Django are described in Aggregation Functions below.

What is Select_related in Django?

Using select_related() Django offers a QuerySet method called select_related() that allows you to retrieve related objects for one-to-many relationships. This translates to a single, more complex QuerySet, but you avoid additional queries when accessing the related objects.


2 Answers

You can use __in:

A.objects.filter(b__in=bs)

or you can avoid creating the bs queryset at all, and follow the relation directly in your query:

A.objects.filter(b__<bcondition>=<bvalue>)

For example, if the filter used to create bs was:

bs = B.objects.filter(name="Banana")

Then you could filter the A objects using:

A.objects.filter(b__name="Banana")

Bear in mind that there are a number of different ways you can filter, and that the filter functionality is quite extensive, so it is worth reviewing the filter documentation

like image 158
Daniel Roseman Avatar answered Oct 11 '22 01:10

Daniel Roseman


Extending Daniel's solution, using __in might return duplicate records if using a related model.

For example:

A.objects.filter(b__in=bs).count() could be more than A.objects.all().count()

For me, using distinct() worked as mentioned in this SO answer

A.objects.filter(b__in=bs).distinct()

like image 1
Anupam Avatar answered Oct 11 '22 00:10

Anupam