Great!
Lets break this down a little.
Your first example is:
a = A.objects.all().prefetch_related(Prefetch('b', B.objects.all()), Prefetch('c', C.objects.all()))
This query needs to be modified a little for it to work with the classes you defined above. The working version is:
a = A.objects.all().prefetch_related(Prefetch('b_set', B.objects.all()), Prefetch('c_set', C.objects.all()))
Now, the first part of this defines a queryset:
a = A.objects.all()
That means that we could rewrite the first example as two lines as:
a_queryset = A.objects.all()
a = a_queryset.prefetch_related(Prefetch('b_set', B.objects.all()), Prefetch('c_set', C.objects.all()))
These two lines produce the same results as the single line as you have written.
Now, I’m going to change the first line here. Instead of producing a queryset, I’m going to create a list:
a = list(A.objects.all())
And now, since I have a list instead of a queryset, I can now use prefetch_related_objects
:
prefetch_related_objects(a, Prefetch('b_set', B.objects.all()), Prefetch('c_set', C.objects.all())
If I wanted to write this as a one line statement, I could then write it like this:
prefetch_related_objects(a:=list(A.objects.all()), Prefetch('b_set', B.objects.all()), Prefetch('c_set', C.objects.all()))
In your second example:
The call to prefetch_related
isn’t necessary. For any one instance of B
, there is only going to be one instance of A
, because the B.aa
field is a foreign key to A
. This means that you would want to use select_related
, making this query:
b = B.objects.all().select_related('aa')
(Using the prefetch_related
call in this situation results in two queries instead of one.)