Django Custom Managers

Andy Byers
2 min readOct 28, 2020

Photo by Chris Ried on Unsplash

We at the Open Library of Humanities and Birkbeck CTP have been working on a Repository system initially built to provide a space for Preprints. We came across an issue where once live data had been imported into the system the main dashboard began to slow down. This wasn’t unexpected — when you add a tonne of data sometimes things get a bit slower — but this was excruciating.

A little investigation with the Django Debug Toolbar showed that we were repeating a bunch of queries over and over again. This is quite easy to tidy up — we added some select_related() and prefetch_related() calls to limit the number of additional queries being made in the templates but due to the nature of one of our models the page remained relatively slow to load. The model looks like this:

class PreprintAuthor(models.Model):
preprint = models.ForeignKey('Preprint')
author = models.ForeignKey('Author')
order = models.PositiveIntegerField(default=0)

When looping through a bunch of preprints on the template we wanted to display the name of the first preprint author. This can be done using the following in the template:

{% for preprint in preprints %}
{{ preprint.preprintauthor_set.0.author.full_name }}
{% endfor %}

We could add a property to get the first author for us but this wouldn’t stop the additional query from being executed. And we use select_related on preprintauthor_set already. To stop the template from executing additonal queries to fech the Author FK we can create a custom manager that will ensure that when a PreprintAuthor is fetched it will get the Author object as well.

class PreprintAuthorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().select_related('author')

With this we pass the heavy lifting over to the SQL backend which is much faster than Python at dealing with this. Now all we need to do is add this to our PreprintAuthor model.

class PreprintAuthor(models.Model):
preprint = models.ForeignKey('Preprint')
author = models.ForeignKey('Author')
order = models.PositiveIntegerField(default=0)
objects = PreprintAuthorManager()

We reduced the number of queries running on the Dashbord to 17 (15 on a second load due to some cache hits!)

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Andy Byers
Andy Byers

Written by Andy Byers

Pub Tech developer for Birkbeck CTP

No responses yet

Write a response