使用自定义管理站点自动注册Django auth模型

ger*_*esc 18 django django-admin django-authentication python-3.4 django-1.8

我使用Django auth和默认的管理站点实现了身份验证管理,但后来我想使用自己的AdminSite重写一些行为:

class OptiAdmin(admin.AdminSite):
    site_title = "Optimizer site's admin"
    #...Other stuff here
Run Code Online (Sandbox Code Playgroud)

然后注册我自己的模型:

admin_site = OptiAdmin(name='opti_admin')
admin.site.register(MyModel, MyModelAdmin)
#Other stuff here
Run Code Online (Sandbox Code Playgroud)

但是当我去管理网站时,我只能看到我刚刚注册的模型,这对我来说听起来不错,但我希望看到这个新的自定义网站中的所有其他应用程序模型,包括auth的用户和组,我不喜欢我不知道如何像默认管理员那样自动执行此操作,请帮助:).

JCo*_*ton 14

  1. 使用简单的__init__()覆盖创建自己的AdminSite .
  2. 导入您的管理员urls.py.

更换Django Admin并autodiscover()以最小的努力获得行为.这是以典型django-admin startproject project方式生成的项目结构:

project/
    manage.py
    project/
        __init__.py
        settings.py
        urls.py
        wsgi.py
        admin.py  # CREATE THIS FILE
Run Code Online (Sandbox Code Playgroud)

project/admin.py :(我认为在项目级别这样做最有意义.)

from django.contrib.admin import *  # PART 1

class MyAdminSite(AdminSite):
    site_header = "My Site"

    def __init__(self, *args, **kwargs):
        super(MyAdminSite, self).__init__(*args, **kwargs)
        self._registry.update(site._registry)  # PART 2

site = MyAdminSite()
Run Code Online (Sandbox Code Playgroud)

project/urls.py(摘录):

from . import admin  # PART 3

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
Run Code Online (Sandbox Code Playgroud)

第1部分是简单的Python.通过将所有内容导入django.contrib.admin到命名空间中,它可以作为替代品.我想你不必这样做,但它有助于保持期望.第3部分,只需连接您的管理员.第2部分是真正的技巧.正如文档所说,autodiscover()被称为做工作.所有自动发现都会INSTALLED_APPS尝试导入一个名为的文件admin.py.导入运行代码当然和代码执行相同的操作来注册模型(例如装饰器和示例方法).没有魔法.您无需使用自定义管理员注册模型(如文档所述).

自动发现看起来比它的register_to kwarg更聪明.这表明您可以自己调用autodiscover()传递自己的管理员.不; 那里没有连线(未来的功能?).分配发生在这里,并固定在本地AdminSite实例这里(或者这里使用的装饰).Django contrib模型注册到该实例,任何第三方库也将注册.这不是你能搞定的东西.

这是诀窍,_registry只是字典映射.让Django自动发现所有的东西,然后只需复制映射.这就是原因self._registry.update(site._registry)."self"是您自定义的AdminSite实例,"site"是Django的实例,您可以使用其中任何一个注册模型.

(最后注意:如果缺少模型,那是因为导入顺序.所有注册到Django的AdminSite都需要在复制之前进行_registry.直接注册到自定义管理员可能是最简单的事情.)


Ala*_*air 11

Django文档建议使用SimpleAdminConfig自定义管理站点.

INSTALLED_APPS = (
    ...
    'django.contrib.admin.apps.SimpleAdminConfig',
    ...
)
Run Code Online (Sandbox Code Playgroud)

这可以防止模型使用默认值进行注册AdminSite.

文档似乎假设您将单独导入模型并将它们添加到您的自定义管理站点:

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

admin_site.register(Group, GroupAdmin)
admin_site.register(User, UserAdmin)
Run Code Online (Sandbox Code Playgroud)

如果您在许多应用程序中都有模型,这将是非常重复的.它没有提供任何建议如何使用您的自定义网站自动注册所有应用程序的模型.

您可以尝试猴子修补admin,并替换admin.site为您自己的.

from django.contrib import admin
admin.site = OptiAdmin(name='opti_admin')
Run Code Online (Sandbox Code Playgroud)

然后,当代码被调用时admin.site.register(),它会在您的管理站点上注册模型.此代码必须在任何模型注册之前运行.您可以尝试将其放入AppConfig应用中,并确保您的应用在上方django.contrib.admin.


小智 5

添加到 JCotton 的精彩答案中:

使用 django 2.0,在自定义管理站点中覆盖site_headersite_title仅适用于该index页面。

要使其与所有管理视图一起使用,请使用以下内容扩展 JCotton 的代码:

    def __init__(self, *args, **kwargs):
        super(MyAdminSite, self).__init__(*args, **kwargs)
        self._registry.update(site._registry)  # PART 2

        for model, model_admin in self._registry.items():
            model_admin.admin_site = self
Run Code Online (Sandbox Code Playgroud)