Skip to content

Related objects

select_related() and prefetch_related() work as in Django, sync and async:

books = [book async for book in Book.objects.select_related("author")]
authors = [author async for author in Author.objects.prefetch_related("books")]
await djox.aprefetch_related_objects(books, "editions")  # on a list you already have
  • Joins the related tables into the query, so it is one query like any other.
  • Runs on djox, and on the fast lane when the rest of the query is simple.
  • Rust builds each object and its related objects, and caches them on each other with Django's own setters.
  • Runs the main query (on the fast lane when it is simple), then Django's own prefetch_related_objects(), unchanged, together on one of djox's threads.
  • One more query per relation, and one round trip from the event loop for all of them.
  • Every kind of relation, and Prefetch() objects, work as in Django.
  • aiterator(chunk_size=...) prefetches for each chunk, like Django's.
  • Inside a transaction, the prefetching runs on the transaction's thread, so it sees its writes.
Why not await each prefetching query?

Django runs those queries from deep inside its own code, level after level, and each level needs the one before it. On a thread, all of them cost one round trip from the event loop; awaited one by one, each would cost one.