如何在Django项目中拥有两个不同的管理员站点?

22

我想在Django项目中创建2个独立的管理站点。

所谓独立是指:它们应该有不同的用户认证,管理不同的模型,并具有不同的外观和URL。

我想这么做的原因是客户希望分别使用不同的部分来管理页面的CMS部分和后台解决方案。

我考虑过只需复制django.contrib.auth应用程序到我的项目树中,给它取不同的名字,并为两者使用单独的admin.site.register()调用。这样,我可以在每个站点上都有其他可用的模型、不同的外观等等。但我不知道如何解决用户认证问题(我需要有不同的用户能够登录CMS和后台)。

是否有人曾经做过这件事,并能给我一些提示?或者我计划的设计是错误的吗?

3个回答

43
你可以继承 Django 的 AdminSite(将其放在项目根目录下的 admin.py 中):
from django.contrib.admin.sites import AdminSite

class MyAdminSite(AdminSite):
    pass
    #or overwrite some methods for different functionality

myadmin = MyAdminSite(name="myadmin")   

至少从1.9版本开始,您需要添加名称参数才能使其正常工作。这用于创建反向URL,因此名称必须是urls.py中的名称。

然后,您可以像使用普通的AdminSite实例一样在应用程序的admin.py中使用它:

from myproject.admin import myadmin
myadmin.register(MyModel_A)

还需要在项目的urls.py中定义一些URL:

from django.urls import path
from myproject.admin import admin, myadmin

urlpatterns = [
    path('admin/', admin.site.urls),
    path('myadmin/', myadmin.urls),
]

还可以参考这个链接:http://docs.djangoproject.com/en/dev/ref/contrib/admin/#adminsite-objects


1
如何在InstalledApps中注册MyAdminSite?基本上,我有租户和共享应用程序。创建了管理员的新实例,并且只需要将此新实例注册到共享应用程序中。 - Robert

10

要在不同的AdminSites中注册模型,只需要创建django.contrib.admin.sites.AdminSite的不同实例,参见此处。

这样你就可以使用两个不同的管理站点来管理不同的模型和具有不同模板的页面。对于身份验证和权限,您应该能够像使用自定义权限一样使用内置的django.contrib.auth(希望其他人能在这方面提供更多帮助)。


1
当我尝试这样做时,在登录后,我会收到“您没有权限编辑任何内容”的消息... - kender
3
您使用的用户应该将is_staff和is_superuser字段设为true。然后,为了区分不同的管理用户以及他们可以访问的内容,请参见http://docs.djangoproject.com/en/1.2/topics/auth/#permissions - Claude Vedovini
好的,我解决了这个问题。但是似乎我无法为两个管理站点设置不同的模板集 - 它们都在模板中查找 'admin /' 目录,即使其中一个使用 'backoffice' 参数创建,它应该将其名称设置为 'backoffice' ... - kender

0

我不确定我在这里报告的发现是否对kender有所帮助,因为除此之外,我不知道他是否仅谈论了两个管理站点,还是每个站点都有一个数据库。这就是我的情况。我想到了一个好主意,我希望我的一个新应用程序拥有自己的数据库和管理页面。

但是,我遇到了Bernhard Vallant的AdminSite子类方法的问题,尽管它似乎是正统且基本正确的方法。我解决了这个问题。

这是我发现必须进行的Bernhard Vallant代码修改:

from django.contrib.admin.sites import AdminSite
class MyAdminSite(AdminSite):
    pass
    #or overwrite some methods for different functionality
myadmin = MyAdminSite(name='anything')

是的,我确实指的是你选择的name='anything'(只要不是'admin')。我已经反复尝试过了,如果不使用除了admin以外的名称分配,每次都会失败。

我遇到的症状是,当我添加第二个数据库并为其创建myadmin,然后使用myadmin.register(My_ModelA)注册模型,并查看两个管理应用程序页面时,使用第二个数据库和myadmin的新应用程序的页面和My_ModelA模型看起来很好,但我的旧管理页面显示其模型的死链接,当我在那里单击一个非死链接的应用程序(使用旧数据库的旧应用程序)时,我得到404代码,表示页面不存在。

此外,我不知道这是否重要,但我在项目urlconf中做了与Bernhard Vallant不同的事情:

from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^admin/', include('mynewapp.urls')),
    url(r'^someword/admin/', include(admin.site.urls)),
)

好的,“某些词语”是无关紧要的---它只是为最终用户外观考虑,不是应用程序或项目的名称。但相关联的管理员是我的旧应用程序和旧数据库的管理员。请注意autodiscover()的包含。在Bernhard Vallant链接的文档中有一些模糊的语言,涉及到当项目urlconf配置如Bernhard Vallant这样使用myadmin导入时,以及对默认管理员的引用。

对于我新应用程序的urlconf,我有:

from django.conf.urls import patterns, url, include
from myproject.admin import myadmin

urlpatterns = patterns('',
    url(r'/', include(myadmin.urls) )
)

urlpatterns += patterns('mynewapp.views',"... url() stuff for mynewapp's views"),
)

尽管在内部将AdminSite实例命名为其他名称是绝对必要的,但我必须补充说,当需要使用admin.ModelAdmin作为父类来装饰mynewapp的admin.py文件时,确实需要使用admin.ModelAdmin。毕竟,myadmin是AdminSite子类的一个实例。因此,我认为它与admin.site平起平坐,而不是与admin相同。

对于像我这样的新手来说,这一切非常令人困惑,因为小写的admin看起来像一个实例,而我不熟悉实例的子类化。所以我假设它不是实例。


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