Additional order_by id added by ModelAdmin

Hi!

I’m ordering a huge model, in its ModelAdmin class, using an ordering variable:

class RevisionAdmin(admin.ModelAdmin):
    ordering = ('-created',)

However, the generated query orders by both fields created and id:

ORDER BY "dl_revision"."created" DESC, "dl_revision"."id" DESC

This causes a huge problem with Postgres optimizer: for some reasons, it does not use foreign key indexes to perform joins (Revision has two foreign key fields), but it makes a full table scan. If I manually remove ordering by id from the query, the optimizer is able to perform joins using indexes.

As a (inefficient) workaround, I created a further combined index with fields ('created', 'id'), and the joins use indexes now.

My question is: is it possible to disable adding the id column to the order by clause, and stick with the fields explicitly requested only?

That’s the exact behaviour that Django’s documentation describes (https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.ordering), and your workaround is kind of suggested there as well.

Have you tried overriding the get_ordering method? I haven’t tried, but by reading the docs and the code, it looks like you can achieve the expected outcome by doing that:

1 Like

Thanks for all your info, now it is much clearer to me what happens behind the scene!

I’ve tried to override get_ordering of class RevisionAdmin:

    def get_ordering(self, request):
        return ['-created']

but the situation does not change: id is added to sorting fields by that _get_deterministic_ordering_() function that is called by the framework after the call to the overridden get_ordering.

It looks like I should redefine the get_ordering() or _get_deterministic_ordering() method of class ChangeView… more precisely, I should define a new class, say RevisionChangeView that extends ChangeView, override its methods, and in some way tell RevisionAdmin to use RevisionChangeView. But I don’t know if it is possible…