Add context to every Django Admin page
Asked Answered
E

3

17

How do I add extra context to all admin webpages?

I use default Django Admin for my admin part of a site.

Here is an url entry for admin:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]

And my apps register their standard view models using:

admin.site.register(Tag, TagAdmin)

My problem, is that I want to display an extra field in admin template header bar and I have no idea how to add this extra context.

My first bet was adding it in url patterns like below:

urlpatterns = [
    url(r'^admin/', admin.site.urls, {'mycontext': '123'}),
]

But that gives an error:

TypeError at /admin/tickets/event/4/change/

change_view() got an unexpected keyword argument 'mycontext'

Can you give any suggestion? I really do not want to modify every AdminModel class I have to insert this context, as I need it on every admin page.

Thanks.

Echinate answered 13/9, 2016 at 18:8 Comment(1)
OP's self-answer did not work for me, possibly because I needed to access the extra data on the admin's index.html page -- this is what did work (however superfluous it may be) https://mcmap.net/q/534481/-django-1-10-override-adminsiteAcrodont
E
9

Found the solution, url registration has to be:

urlpatterns = [
    url(r'^admin/', admin.site.urls, {'extra_context': {'mycontext': '123'}}),
]

Its a context dictionary inside of a dictionary with 'extra_context' as a key.

Echinate answered 13/9, 2016 at 18:25 Comment(2)
do you know what view this would get added in, if say I wanted to add a specific queryset?Acrodont
After taking your advice (which fixed the problem I was trying to solve very well!) I found that the "change password" form in the Django Admin was broken. This seems like it may be a bug in Django. To get both the extra context and the change password form I had to use Django's ModelAdmin 'add_view' and 'change_view' methods on the individual forms after all. https://mcmap.net/q/746106/-user_change_password-got-an-unexpected-keyword-argument-39-extra_context-39Foxhole
R
5

Another technique, more complex but allows different context per request (probably unavailable at OP time):

my_project/admin.py (create if missing)

from django.contrib import admin
from django.contrib.admin.apps import AdminConfig


class MyAdminConfig(AdminConfig):
    default_site = 'my_project.admin.MyAdminSite'


class MyAdminSite(admin.AdminSite):
    def each_context(self, request):
        context = super().each_context(request)
        context.update({
            "whatever": "this is",
            "just a": "dict",
        })
        return context

settings.py

INSTALLED_APPS = [
    ...
    'my_project.admin.MyAdminConfig',  # replaces 'django.contrib.admin'
    ...

The replace / extend admin class code is taken from the official docs except this is all in one file.

Renshaw answered 7/9, 2019 at 18:25 Comment(2)
ModuleNotFoundError: No module named 'my_project', when I add it in INSTALLED_APPSHax
@MartinTaleski That looks like a path issue. Be sure to use the directory that holds your wsgi.py instead of my_project, or create a new module inside the project root and use its name. BTW also thanks for the edit. Dumb me clicked "rollback" by accident, sorry.Renshaw
P
0

You can monkey-patch the default admin site like so:

Top level urls.py:

from django.contrib import admin
from django.urls import include, path

...

# Store a reference to the default each_context so we don't cause an infinite loop when we override it.
base_admin_context = admin.site.each_context

def custom_admin_context(request):
    context = base_admin_context(request)
    
    # Do anything we want with the context
    # Example: adding a custom sidebar nav section at the top
    context["available_apps"].insert(
        0,
        {
            "name": "Extra stuff",
            "app_url": "/admin/extra/",
            "has_module_perms": True,
            "models": [
                {
                    "object_name": None,
                    "name": "A custom admin dashboard",
                    "admin_url": "/admin/extra/dashboard",
                }
            ],
        },
    )
    return context

admin.site.each_context = custom_admin_context

...

urlpatterns = [...]

If you are already overriding other default admin.site values, this can be a low-complexity solution.

Poriferous answered 23/2 at 22:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.