如何让非员工用户访问Django管理站点?

11 投票
3 回答
6990 浏览
提问于 2025-04-16 06:05

我想要建立一个第二个管理网站,这个网站只提供第一个管理网站的一部分功能。这是可以做到的,具体的做法在Django文档中有说明。

不过,我想限制对第一个管理网站的访问。有些用户可以访问第二个网站,但不能访问第一个网站。

为了实现这个功能,我希望这些用户不在工作人员列表中(也就是设置is_staff=False),并且重写一下AdminSite.has_permission这个方法。

class SecondaryAdminSite(AdminSite):
    
    def has_permission(self, request):
        if request.user.is_anonymous:
            try:
                username = request.POST['username']
                password = request.POST['password']
            except KeyError:
                return False
            try:
                user = User.objects.get(username = username)
                if user.check_password(password):
                    return user.has_perm('app.change_onlythistable')
                else:
                    return False
            except User.DoesNotExist:
                return False
        else:
            return request.user.has_perm('app.change_onlythistable')

可惜的是,这种方法不奏效。用户可以登录,但在第二个管理网站上什么都看不到。

这个方法有什么问题呢?有没有什么想法可以实现这个功能?

提前谢谢大家!

3 个回答

-1

这个方法有什么问题?有没有想法如何实现这个功能?

这个方法的问题在于,权限和用户组已经可以满足你的需求。如果你只是想把用户分开,其实没必要去重新定义 AdminSite。

我觉得这可能就是为什么这个功能的文档写得这么少的原因。

7

这是我在使用 Django >= 3.2 时找到的解决办法。

  • 首先,创建一个 AdminSite 的子类。
  • 接着,重写 has_permission() 方法,去掉对 is_staff 的检查。
  • 然后,重写 login_form,让它使用 AuthenticationForm
    • AdminSite 默认使用的是 AdminAuthenticationForm,这个类是基于 AuthenticationForm 扩展的,并且增加了对 is_staff 的检查。

代码

# PROJECT/APP/admin.py

from django.contrib.admin import AdminSite
from django.contrib.admin.forms import AuthenticationForm


class MyAdminSite(AdminSite):
    """
    App-specific admin site implementation
    """

    login_form = AuthenticationForm

    site_header = 'Todomon'

    def has_permission(self, request):
        """
        Checks if the current user has access.
        """
        return request.user.is_active


site = MyAdminSite(name='myadmin')

4

我觉得你现在的做法应该是可行的:http://code.djangoproject.com/ticket/14434(5周前关闭)

不过,除了使用 staff_member_required 装饰器之外,"is_staff" 的检查还是在两个地方进行的:

  • django.contrib.admin.forms.AdminAuthenticationForm.clean()

    在 "has_permission()" 的基础上,你需要为你的非员工 AdminSite 提供一个不进行 is_staff 检查的 "login_form",所以可以通过继承并相应地调整 clean() 方法来实现。

  • templates/admin/base.html

    这个文件需要稍微定制一下。id 为 "user-tools" 的 div 只会显示给活跃的员工。我猜这是因为登录表单也使用了这个模板,而某人可能以活跃的非员工身份登录,但仍然不应该看到那些链接。

撰写回答