[Fixed]-Django admin, extending admin with custom views

19๐Ÿ‘

โœ…

This guide looks quite old. I would rather advise you to follow django docs.

someapp/admin.py

from django.contrib.admin import AdminSite
from django.http import HttpResponse

class MyAdminSite(AdminSite):

     def get_urls(self):
         from django.urls import path
         urls = super().get_urls()
         urls += [
             path('my_view/', self.admin_view(self.my_view))
         ]
         return urls

     def my_view(self, request):
         return HttpResponse("Hello!")

admin_site = MyAdminSite()

Source: https://github.com/django/django/blob/2.2/django/contrib/admin/sites.py#L194-L205

You should also update your project/urls.py and replace path('admin/', admin.site.urls) by path('admin/', admin_site.urls). Donโ€™t forget to from someapp.admin import admin_site before.

๐Ÿ‘คAntoine Pinsard

11๐Ÿ‘

The guide you linked is old and I was surprised to not find anything directly answering your question in the last year or so.

  1. Create a new Admin Site in your appโ€™s admin.py or in a convenient place.
  2. Create a function in the new AdminSite that augments the get_urls() function with your extra urls.
  3. Make sure your project urls.py links to the newly created AdminSite.

The below works with Python 3.5.1 and Django 1.9.6.


my_app/admin.py

from django.contrib import admin
from django.contrib.admin import AdminSite
from django.http import HttpResponse

from my_app.models import SomeModel


class MyAdminSite(AdminSite):

    def custom_view(self, request):
        return HttpResponse("Test")

    def get_urls(self):
        from django.conf.urls import url
        urls = super(MyAdminSite, self).get_urls()
        urls += [
            url(r'^custom_view/$', self.admin_view(self.custom_view))
        ]
        return urls

admin_site = MyAdminSite()


@admin.register(SomeModel, site=admin_site)
class SomeModelAdmin(admin.ModelAdmin):
    pass

my_project/urls.py

from django.conf.urls import url, include

from my_app.admin import admin_site

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

1๐Ÿ‘

For Django 1.4+ here is the solution:

from django.conf.urls import url
from django.contrib import admin
from .models import MyModel


class MyAdmin(admin.ModelAdmin):
    list_display = (...)

    def custom_admin_view(self, request):
        # your logic here
        if request.method == 'POST':
            ...
        else:
            ...
        return HttpResponse(...)

    def get_urls(self):
        additional_urls = [
            url(r'^custom/$', self.admin_site.admin_view(self.custom_admin_view), name='custom')
        ]
        # append your custom URL BEFORE default ones
        return additional_urls + super().get_urls()


admin.site.register(MyModel, MyAdmin)

Itโ€™s important to append your custom URL before all others. Otherwise you might get redirect to admin change_view instead.

๐Ÿ‘คAnaPana

0๐Ÿ‘

This code below will override the default admin site to write your custom view.

Works for Django >= 2.1 :

###myproject/admin.py

from django.contrib import admin
from django.http import HttpResponse

class MyAdminSite(admin.AdminSite):

    def my_view(self, request): # your custom view function
        return HttpResponse("Test")

    def get_urls(self):
        from django.urls import path

        urlpatterns = super().get_urls()
        urlpatterns += [
            path('my_view/', self.admin_view(self.my_view))
        ]
        return urlpatterns

###myproject/apps.py

from django.contrib.admin.apps import AdminConfig

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

###myproject/settings.py

INSTALLED_APPS = [
    ...
    'myproject.apps.MyAdminConfig',  # replaces 'django.contrib.admin'
    ...
]

Then go to http://127.0.0.1:8000/admin/my_view/

๐Ÿ‘คazissan

Leave a comment