Working on a DRF endpoint I expierenced an issue with prefetch_related and first called on the prefetched set. Let's consider two models: X and Y; Y contains a foreign key to X.
Then I perform following code:
qs = X.objects.all().prefetch_related("y_set")
for x in qs:
for y in x.y_set.all():
print(e)
Everything is OK, django performs 2 queries as expected.
Then I perform:
for x in qs:
for y in x.y_set.all():
print(e)
first = x.y_set.first()
In this example, Django perform n+2 queries what is not expected (at least for me).
I found a workaround with:
for x in qs:
for y in x.y_set.all():
print(e)
first = y_set.all()[0] if y_set.all() else None
but it's not satisfying for me - I feel like checking if qs is not empty and then taking the first element is a bit messy, I'd definitely prefer to use first or some other function that hides this logic.
Can anyone explain why first doesn't use prefetched cache or can you give me a tip how to handle it a bit clearer? (I don't want to add a wrapper to handle that, I prefer native django orm solution. Also I can't just take the first element from the loop - I simplified the example a lot)
Thanks in advance!