Django (1.10)如何覆盖AdminSite?

12

我尝试使用自己的自定义类覆盖AdminSite类。我按照Django文档中的教程进行了操作:https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#customizing-adminsite,但是并没有奏效。具体来说,我想用自己的类覆盖原始的AdminSite而不是仅仅在项目中添加另一个管理站点。

我创建了自己的自定义类MyAdminSite,它继承自该类

from django.contrib.admin import AdminSite


class MyAdminSite(AdminSite):
    pass

然后在我的应用程序urls.py文件中,我已经添加了:

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),
]

看起来它是有效的,但管理模型注册到AdminSite而不是MyAdminSite。

我尝试了三种方式将模型注册到我的自定义站点:

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

这种方式可以将模型注册到原始的AdminSite。

第二种方式:

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

那样做不起作用并导致异常。ModelAdmin类没有传递给register方法。

最后一种方法:

那樣做沒有效果並導致異常。ModelAdmin類未傳遞給register方法。

最後一種方法:

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

这个方法可行,但是在管理界面上,我只能看到我的模型而无法看到Django admin的模型(用户和组)。

我该如何永久性地覆盖admin.site并将所有模型注册到MyAdminSite?


你是如何将你的模型注册到自定义管理站点中的? - knbk
你链接的文档中有什么让你认为这会起作用? - Daniel Roseman
文档站点只是一个例子,我知道还有其他不同于我想要的东西。我还尝试了很多其他教程和方法,但它们都不起作用。 - ostojan
Django 2.1将拥有一个钩子,可以轻松地覆盖默认的管理站点。链接 - Alasdair
3个回答

15

从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)

来自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
]

6

我没有找到解决问题的方法,但是我已经想出了一个解决办法。

首先,我们需要在应用程序中创建模块(例如admin.py),然后扩展AdminSite类:

from django.contrib.admin import AdminSite

class MyAdminSite(AdminSite):
    ...

在模块底部,我们需要创建MyAdminSite的实例并注册Django的内置模型:

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

必要的导入:

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

在我们的站点URL模块中,我们需要覆盖原始站点对象:
from .admin import site

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

我们需要做的最后一件事是注册我们的模型。有一件事需要记住,就是我们不能像这样使用注册装饰器:

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

或者:

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

我们需要定义ModelAdmin类,然后在MyAdminSite对象上调用register:
class MyModelAdmin(admin.ModelAdmin):
    ...
admin.site.register(MyModel, MyModelAdmin)

这是我唯一可行的解决方案。

3
很有帮助!可惜我们必须费尽周折才能扩展AdminSite并使其正常工作... - Ícaro
1
@icarovirtual 太对了。尽管我只需要在我的管理员“index.html”页面中添加2个额外的上下文变量,但最终我还是使用了这个答案。 - kt-0

1
我遇到了类似的问题。我使用的是Django 2.1,上面评论中the hook并没有对我起作用。而且我也不能像下面这样导入GroupAdmin和UserAdmin。
from django.contrib.auth.models import Group, User
from django.contrib.auth.admin import GroupAdmin, UserAdmin

导入GroupAdmin或UserAdmin会出现错误,但我无法确定具体原因。因此,我的解决方法是(在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),
    ]

这里的想法是从默认管理站点复制注册模型。也许这样做不太好,但我找不到其他可行的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接