Django:如何使用两个不同的AdminSite实例并注册不同的模型

4

除了通常的管理员,我想为非员工用户创建一个有限的管理员。这个管理员网站将有不同的已注册的ModelAdmin

我在我的项目目录中创建了一个名为/useradmin/的文件夹,并类似于contrib/admin/_init_.py添加了一个autodiscover()函数,它将注册在useradmin.py模块中定义的模型,而不是在admin.py中定义的模型:

# useradmin/__init__.py
def autodiscover():
# Same as admin.autodiscover() but registers useradmin.py modules
...
for app in settings.INSTALLED_APPS:
    mod = import_module(app)
    try:
        before_import_registry = copy.copy(site._registry)
        import_module('%s.useradmin' % app)
    except:
        site._registry = before_import_registry
        if module_has_submodule(mod, 'useradmin'):
            raise

我还创建了useradmin/sites.py文件,覆盖了类似contrib/admin/sites的AdminSite。
# useradmin/sites.py
class UserAdminSite(AdminSite):
    def has_permission(self, request):
        # Don't care if the user is staff
        return request.user.is_active

    def login(self, request):
        # Do the login stuff but don't care if the user is staff
        if request.user.is_authenticated():
            ...
        else:
            ...

site = UserAdminSite(name='useradmin')

在项目的URL中:
# urls.py
from django.contrib import admin
import useradmin

admin.autodiscover()
useradmin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/', include(admin.site.urls)),
    (r'^useradmin/', include(useradmin.site.urls)),
)

我尝试在app目录下的admin.py和useradmin.py模块中注册不同的模型:

# products/useradmin.py
import useradmin
class ProductAdmin(useradmin.ModelAdmin):
    pass
useradmin.site.register(Product, ProductAdmin)

但是当我在useradmin.py中像这样注册模型useradmin.site.register(Product, ProductAdmin)时,我会得到一个'module' object has no attribute 'ModelAdmin'的异常。虽然当我通过shell尝试时;

import useradmin
from useradmin import ModelAdmin

没有引发任何异常。

有什么想法可能出了问题吗?

编辑:

我尝试按照 @Luke 的方式排列代码,尽可能地简化如下: (文件路径相对于项目根目录)

# admin.py
from django.contrib.admin import autodiscover
from django.contrib.admin.sites import AdminSite
user_site = AdminSite(name='useradmin')

# urls.py (does not even have url patterns; just calls autodiscover())
import admin
admin.autodiscover()

# products/admin.py
import admin
from products.models import Product
admin.user_site.register(Product)

作为结果,当在products/admin.py中调用admin.user_site.register(Product)时,我会得到一个AttributeError: 'module' object has no attribute 'user_site'错误。

有什么想法吗?

解决方案:

我不知道是否有更好的方法,但是将项目根目录中的admin.py重命名为useradmin.py并相应地更新导入可以解决最后一种情况,即命名和导入冲突。

1个回答

1

useradmin 是否定义了 ModelAdmin 类,或者您是从 contrib.admin 导入的?我在您提供的代码中没有看到设置该类的任何地方。

话虽如此,有一种更简单的方法来实现这个:只需 初始化两个 AdminSites,然后将它们连接到您想要的 URL(甚至可以将它们放在同一个 urlconf 中)。


ModelAdmin是从contrib.admin中导入的,位于useradmin/init.py中。useradmin/init.py和contrib.admin.init.py中的导入语句是相同的。因此,我可以像这样导入ModelAdmin:from useradmin import ModelAdmin。我想要一些超出文档所述方式的自定义。例如,用户在具有FK字段添加权限的情况下不应在管理员主页面中看到某些查找模型。因此,我需要实现自己的autodiscover()来仅向用户的管理站点注册某些模型。 - onurmatik
你可以将一些模型注册到每个AdminSite实例中(autodiscover为你做的唯一一件事情就是查找admin.py文件),而无需进行所有这些重复操作 - 你甚至可以编写自己的AdminSite类,继承自Django的类,以便按照你的意愿进行设置。 - girasquid
所以我可以定义另一个AdminSite实例,例如user_admin = AdminSite(name='user_admin'),并使用原始的admin.site.register(ModelA)注册一些模型,以及使用admin.user_site(ModelB)注册其他模型。这是有意义的。但是我仍然无法在实践中解决循环导入问题。如果/当我成功时,我会发布代码片段。谢谢。 - onurmatik
最后一种情况似乎是命名冲突。我将项目根目录中的 admin.py 更改为 useradmin.py 并相应地更新了导入。现在它按预期工作。谢谢。 - onurmatik

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