Search code examples
djangodjango-admin

How do you override Django's admin app_index?


I'm very familiar with how to override Django's admin templates, but I haven't been able to find any instructions on how to properly override the context available to said templates. For example this page:

/admin/users/

The style for this page can be overridden by creating a file at:

root/users/templates/admin/users/app_index.html

But what if I want to do some more Python-level stuff before the template is loaded? Specifically in my case I want to generate a sort of dashboard for /admin/users/ and for that I'll need to run a rather elaborate query.

Now I know I could hack this by creating a template tag that does the query for me, but frankly that's pretty dirty as you're hitting the database from a template, so I'd like to do this better if such a way exists.

If however you can state with confidence (and convincingly) that this simply can't be done without rewriting django.contrib.admin.sites.AdminSite.app_index, then I'll flag your answer as correct and go with my ugly hack.


Solution

  • It can be done, and without rewriting app_index. Since AdminSite is intended to be customized through subclassing.

    Looking at the AdminSite implementation, you can see app_index has a keyword argument extra_context. You can utilize this for your purposes to avoid rewriting as follows

    from django.contrib.admin import AdminSite
    
    class MyAdmin(AdminSite):
        def app_index(self, request, app_label, extra_context=None):
            if not extra_context:
                extra_context = {}
            extra_context['my_new_key'] = 'val'
    
            super().app_index(request, app_label, extra_context=extra_context)
    

    The problem then arises that you would need to instantiate your custom site and use it to set your urls and register model admins. If this is inconvenient as suggested by Alasdair, you might consider this.

    All that being said, you will still hit the database on the request anyway, similar to your concern with the tag. Only caching would solve that.