ostojan ostojan - 1 month ago 19
Python Question

Django (1.10) override AdminSite

I've tried to override AdminSite class with my own custom class. I followed tutorial from django's documentation: https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#customizing-adminsite but it didn't work. To be specific, I'd like to override original AdminSite with my own class and not just add another admin site into my project.

I've created my custom class MyAdminSite which inherit from class

from django.contrib.admin import AdminSite


class MyAdminSite(AdminSite):
pass


Then in my app urls.py I've add:

from django.conf.urls import url, include
import django.contrib.admin as admin
from .admin_site import MyAdminSite

admin.site = MyAdminSite()
admin.autodiscover()


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


It seemed to work, but admin models are register to AdminSite insted of MyAdminSite.

I tried three ways of register models to my custom site:

@admin.register(Model)
class ModelAdmin(model.AdminModel):
...


This way models are registered to original AdminSite.

Second way:

@admin.site.register(Model):
class ModelAdmin(model.AdminModel):
...


That don't work and cause exception. The ModelAdmin class isn't passed to register method.

Last way:

class ModelAdmin(model.AdminModel):
...
admin.site.register(Model, ModelAdmin)


That works, but on admin site I can see only my models not models from Django admin (Users and Groups).

How can I permanently override admin.site and register all models to MyAdminSite?

Answer

I didn't found the solution to my problem, but I have made a workaround.

First we need to create module in our app (e.g. admin.py) and then extend class AdminSite:

from django.contrib.admin import AdminSite

class MyAdminSite(AdminSite):
    ...

Then on bottom of module we need to create instance of our MyAdminSite and register built-in models from Django:

site = MyAdminSite()
site.register(Group, GroupAdmin)
site.register(User, UserAdmin)

Necessary imports:

from django.contrib.auth.models import Group, User
from django.contrib.auth.admin import GroupAdmin, UserAdmin

In our site url module we need to override original site object:

from .admin import site

admin.site = site
admin.autodiscover()
...
url(r'^admin/', admin.site.urls)
...

Last change we need to do is register our models. One thing we need to remeber is that we can't use register as decorator like that:

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    ...

or:

@admin.site.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    ...

We need to define our ModelAdmin class and then call register on our MyAdminSite object:

class MyModelAdmin(admin.ModelAdmin):
    ...
admin.site.register(MyModel, MyModelAdmin

This is the only solution that is working for me.