2

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.

Daniel Quinn
  • 6,010
  • 6
  • 38
  • 61
  • 2
    I think that overriding `AdminSite.app_index` would be correct the way to do it. But since registering your all your `ModelAdmin`s with a custom admin site is inconvenient, and monkey patching `AdminSite` would be hacky, a template tag is the pragmatic approach. I'll leave the convincing to somebody else ;) – Alasdair Jan 20 '17 at 19:16
  • This was my thinking as well, but was hoping that I was missing something. – Daniel Quinn Jan 20 '17 at 19:19

2 Answers2

3

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.

Community
  • 1
  • 1
yummies
  • 686
  • 6
  • 14
  • 1
    I'm not concerned about hitting the database, only that it be done at the proper layer in the stack, ie. not by the template. But this looks like a good place to start. Thanks! – Daniel Quinn Jan 20 '17 at 22:02
0

An Alternative might be to override the app_index.html template and use an inclusion tag or any other custom templatetag to incorporate your custom view.

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 03 '23 at 05:22