使用自定义管理站点自动注册 Django 身份验证模型

Posted

技术标签:

【中文标题】使用自定义管理站点自动注册 Django 身份验证模型【英文标题】:Auto register Django auth models using custom admin site 【发布时间】:2015-12-13 06:20:48 【问题描述】:

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

class OptiAdmin(admin.AdminSite):
    site_title = "Optimizer site's admin"
    #...Other stuff here

然后注册我自己的模型:

admin_site = OptiAdmin(name='opti_admin')
admin.site.register(MyModel, MyModelAdmin)
#Other stuff here

但是当我进入管理站点时,我只能看到我刚刚注册的模型,这对我来说听起来很公平,但我希望看到这个新的自定义站点中的所有其他应用程序模型,包括身份验证的用户和组而且我不知道如何像默认管理员那样自动执行此操作,请帮助:)。

【问题讨论】:

【参考方案1】:
    使用简单的 __init__() 覆盖创建您自己的 AdminSite。 将你的管理员导入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

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

project/urls.py (sn-p):

from . import admin  # PART 3

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

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

自动发现看起来比使用 register_to kwarg 更智能。这表明您可以通过自己的管理员调用 autodiscover() 。没有;那里没有接线(未来的功能?)。分配发生在here 并固定到本机AdminSite 实例here(或使用装饰器的here)。 Django contrib 模型注册到该实例,任何第三方库也将注册。这不是你可以挂钩的东西。

这里有个窍门,_registry 只是一个字典映射。让 Django 自动发现所有内容,然后复制映射。这就是self._registry.update(site._registry) 起作用的原因。 “self”是您自定义的 AdminSite 实例,“site”是 Django 的实例,您可以使用其中任何一个注册模型。

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

【讨论】:

我刚刚在 Django 1.11 中使用自定义 AdminSite 实例进行了尝试。注册模型采用父 AdminSite 的所有默认值,而不是子实例的相关默认值。例如,site_title 在我的自定义实例中设置为不同的值,当查看任何已自动注册的模型时,Django 默认值仅对这些模型可见。文档确实说您应该在使用自定义实例时手动注册。 docs.djangoproject.com/en/1.11/ref/contrib/admin/… 您是否尝试过self._registry.update() Django 自动注册/构建其 AdminSite 的步骤,然后复制映射?这可能会覆盖现有值,因此请尝试在调用 __init__() 之后设置您的 AdminSite 属性(如 site_title、标题、url 等)。 是的,我按照您发布的所有方法都试过了。因此,如果我理解正确,您希望我在 self._registry_update 之后的 init 函数中重新定义 site_header 等? 不错,值得一试。看了一眼1.11的代码,和1.9一样。尝试在过程中使用 print() 或 pdb 断点进行检查。你可能都说对了(除了总是浪费时间的一件事)。 Django 2.0 中测试了这段代码。设置 site_headersite_title 仅适用于 indexapp index 页面。 app models 但仍显示 Django Administration【参考方案2】:

Django 文档建议将SimpleAdminConfig 与自定义管理站点一起使用。

INSTALLED_APPS = (
    ...
    'django.contrib.admin.apps.SimpleAdminConfig',
    ...
)

这会阻止模型注册到默认的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)

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

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

from django.contrib import admin
admin.site = OptiAdmin(name='opti_admin')

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

【讨论】:

@Alasdir Thks,我将在今天晚些时候尝试这个猴子补丁,听起来它可以工作。此外,手动注册肯定会完成这项工作,但我需要在我想要包含的每个应用程序中注册每个模型 它适用于我使用import django.contrib.admin django.contrib.admin.sites.site = admin_site django.contrib.admin.site = admin_site【参考方案3】:

添加到 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

【讨论】:

【参考方案4】:

只需像这样在您的 CustomAdminSite 类中包含 init 方法。

    class CustomAdminSite(admin.AdminSite):
        def __init__(self, *args, **kwargs):
            super(CustomAdminSite, self).__init__(*args, **kwargs)
            self._registry.update(admin.site._registry)

【讨论】:

以上是关于使用自定义管理站点自动注册 Django 身份验证模型的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Windows 身份验证并注册自定义身份验证管理器

Django站点管理

在自定义管理页面中显示正确的 django 身份验证框架信息

Django基础概念和MVT架构

Django 管理员无法使用自定义用户模型正确登录

如何使用 django-allauth 进行自定义注册?