'How to enable django admin sidebar navigation in a custom view?

I have a view inheriting from LoginRequiredMixin, TemplateView, which renders some data using the admin/base_site.html template as the base. I treat it as a part of the admin interface, so it requires an administrator login. I'd like to make this view a little bit more a part of the Django admin interface by enabling the standard sidebar navigation on the left-hand side.

Note that I don't have a custom ModelAdmin definition anywhere, I simply render the template at some predefined URL. There are no models used in the interface either, it parses and displays data from database-unrelated sources.

Currently, I just build the required context data manually, e.g.:

data = super().get_context_data(**kwargs)
data.update(**{
    "is_popup": False,
    "site_header": None,
    "is_nav_sidebar_enabled": True,
    "has_permission": True,
    "title": "My title",
    "subtitle": None,
    "site_url": None,
    "available_apps": []
})

The sidebar is visible, but displays an error message:

Error message: You don't have permission to view or edit anything

Adding an app to available_apps ("available_apps": ["my_app"]) doesn't help either:

Rendered sidebar with no data

So my question is - how do I do that? Is there a class I can inherit from to achieve this behaviour? Or a method I can call to get all required context data for base_site.html? Or perhaps I should insert some information in my template? Perhaps I need an AdminSite object, or can somehow call methods of the default one?



Solution 1:[1]

By accident I noticed there is a DefaultAdminSite object in django.contrib.admin.sites, and it's instantiated as site. Therefore, in my case, simply using site is sufficient.

from django.contrib.admin import AdminSite
from django.contrib.admin.sites import site
admin_site: AdminSite = site
data.update(**admin_site.each_context(self.request))

Furthermore, turns out I can just use the apps in case importing site would be an issue, just like DefaultAdminSite does it:

AdminSiteClass = import_string(apps.get_app_config("admin").default_site)
self._wrapped = AdminSiteClass()

Solution 2:[2]

The app_list.html template which is included in your base template requires a context variable available_apps with a structure as described here.

As you probably won't be able to make this include work properly with your app you could also override the {% block nav-sidebar %} in your base template and provide some HTML that fits your use-case.

But after all it's probably not such a good idea to reuse templates which are made for a different app (admin) with your app because it's difficult to predict how they will behave, what their requirements are and beyond this maintainance in the long term will also be a problem as they might change with future Django versions.

Solution 3:[3]

You have to include django admin's default context variables used in the template. This can be done by calling each_context function:


data.update(self.admin_site.each_context(request))

I also have custom admin views and templates in my projects and this works well for me.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Kacper Floria?ski
Solution 2 Bernhard Vallant
Solution 3