Additional order_by id added by ModelAdmin


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 (, 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…