4

I am using prefetch_related when querying a model that have several m2m relationships:

qs = context.mymodel_set.prefetch_related('things1', 'things2', 'things3')

So that when I do this there is no need to perform an additional query to get things1, they should have been fetched already:

r = list(qs)
r[0].things1.all()

But what if I do r[0].things1.exists()? Will this generate a new query? Or will it use the prefetched information? If it generates a new query, does that mean that going for r[0].things1.all() for the purposes of existence checking is more efficient?

PS: cached information being in desync with the database does not worry me for this particular question.

dabadaba
  • 9,064
  • 21
  • 85
  • 155

2 Answers2

3

It's easy to check the queries that Django is running for yourself.

When I tried it, it appeared that obj.things.exists() did not cause any additional queries when things was prefetched.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • I am testing this with `shell_plus --print-sql` and `r[0].things1.all()` seems to be querying the db. But when I do `r[0].things1.exists()` nothing is printed out. – dabadaba Jun 01 '18 at 13:22
  • It looks like I was wrong - it appears that `exists()` does not cause an additional query when the `things` has been prefetched. Your `r[0].things.all()` should not cause any additional queries - that's the point of prefetching. You haven't shown what the queries are -- perhaps your `__str__` method causes foreign key lookups. – Alasdair Jun 01 '18 at 14:29
0

To capture only objects having relation with things1 it can go in the query like this:

context.mymodel_set.prefetch_related(
   'things1', 'things2', 'things3'
).filter(
    things1__isnull=False
)
Sławomir Lenart
  • 7,543
  • 4
  • 45
  • 61