Django (1.10) override AdminSite
Asked Answered
R

3

12

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?

Redden answered 17/10, 2016 at 15:18 Comment(4)
How are you registering your models to your custom admin site?Headstall
What in the docs you link to made you think this would work?Swaraj
The docs site was just an example and I know that there is something else than what I want. I've also tried plenty of other tutorials and other methods but none of them works.Redden
Django 2.1 will have a hook to override the default admin site easily.Rossuck
R
6

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.

Redden answered 26/10, 2016 at 15:12 Comment(2)
This is helpful! Too bad we have to go to such lengths to extend the AdminSite and make it work properly...Jenicejeniece
@icarovirtual So true. I ended up using this answer even though all I needed to do was add 2 extra context variables to my admin's index.html pageBackfield
T
15

From myapp/admin.py:

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

from .models import MyModel #This is my app's model

# Custom admin site
class MyAdminSite(AdminSite):
    site_header = 'My Project Title'
    site_title  = 'My Project Title Administration'
    index_title = 'My Project Title Administration'
    # You can add on more attributes if you need 
    # Check out https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#adminsite-objects

# Create admin_site object from MyAdminSite
admin_site = MyAdminSite(name='my_project_admin')

# Register the models
class MyModelAdmin(admin.ModelAdmin):
    list_display = ('id', 'description')

admin_site.register(MyModel, MyModelAdmin)

# Create and register all of your models
# ....

# This is the default Django Contrib Admin user / group object
# Add this if you need to edit the users / groups in your custom admin
admin_site.register(Group, GroupAdmin)
admin_site.register(User, UserAdmin)

From myproject/urls.py

from django.conf.urls import url
from django.contrib import admin
from myapp.admin import admin_site ##! Important..Import your object (admin_site) instead of your class (MyAdminSite)

urlpatterns = [
    url(r'^admin/', admin_site.urls), #Now all /admin/ will go to our custom admin
]
Trouper answered 2/7, 2017 at 16:57 Comment(0)
R
6

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.

Redden answered 26/10, 2016 at 15:12 Comment(2)
This is helpful! Too bad we have to go to such lengths to extend the AdminSite and make it work properly...Jenicejeniece
@icarovirtual So true. I ended up using this answer even though all I needed to do was add 2 extra context variables to my admin's index.html pageBackfield
C
1

I faced a similar problem. I used Django 2.1 and the hook from the comments above didn't work for me. And also I was not able to import GroupAdmin and UserAdmin, like so

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

Importing GroupAdmin or UserAdmin broke the code for some reason. I was not able to define the exact reason.

So my workaround was (in project/urls.py):

from django.conf.urls import include, url
from django.contrib.admin import site
from project.admin import myadmin

myadmin._registry.update(site._registry)

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

The idea here is to copy registered models from default admin site. Maybe it's not good to do so, but I could not find anything else working.

Chillon answered 28/8, 2018 at 0:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.