Minimize database queries using Django's QuerySet.extra()

Because of it’s origins in a busy newsroom, Django makes optimizing web application performance a breeze. Some high-level examples of this are the awesome cache framework and the shared nothing approach. But even with these tools it’s important to write code that performs as efficiently as possible – otherwise things like caching aren’t really optimizing, they’re simply minimizing performance loss due to bad code.

(“Make it more awesome” and “make it suck less” are two very different directives).

Minimizing database queries is a preemptive measure you can take to ensure your application is built to scale right from the start. Luckily, Django makes it very easy to bake this right into your code.

The extra() function makes it possible to attach object attributes which normally would require an additional database query. A simple example is probably the clearest way to illustrate this.

I’ll create two basic models, Author and Book, and a template which lists all authors and the number of books they’ve written. The first method uses the RelatedManager API Django automatically gives us, and the second method uses a custom Manager class which encapsulates the extra() function.

Method #1: Using RelatedManager.count()

So here are the super-simple models we’ll be working with: