2. How to optimize queries in Django admin?¶
If you have a lot of calculated fields in your admin, you can be running multiple queries per object leading to your admin can becoming quite slow.
To fix this you can override the get_queryset
method on model admin to annotate the calculated fields.
Lets take the example of this ModelAdmin
we have for Origin
:
@admin.register(Origin)
class OriginAdmin(admin.ModelAdmin):
list_display = ("name", "hero_count", "villain_count")
def hero_count(self, obj):
return obj.hero_set.count()
def villain_count(self, obj):
return obj.villain_set.count()
This adds two extra queries per row in your listview page. To fix this you can override the get_queryset
to annotate the counted fields,
and then use the annotated fields in your ModelAdmin methods.
With the changes, your ModelAdmin field looks like this:
@admin.register(Origin)
class OriginAdmin(admin.ModelAdmin):
list_display = ("name", "hero_count", "villain_count")
def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.annotate(
_hero_count=Count("hero", distinct=True),
_villain_count=Count("villain", distinct=True),
)
return queryset
def hero_count(self, obj):
return obj._hero_count
def villain_count(self, obj):
return obj._villain_count
There are no per object extra queries. Your admin continues to look like it did before the annotate
call.
![_images/calculated_field.png](_images/calculated_field.png)