You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Admin权限配置:普通管理员可访问非User模型的方案

问题描述

我正在开发一个校园网站,需要在Django Admin中实现以下权限配置:

  • 超级管理员(拥有is_staff和is_superuser权限)可以创建、管理所有用户
  • 普通管理员(仅拥有is_staff权限)无法访问User模型,但能正常操作其他业务模型

目前普通管理员登录Admin后会收到「You don’t have permission to view or edit anything.」错误,超级管理员操作一切正常,需要调整权限配置实现需求。


managers.py

from django.contrib.auth.models import BaseUserManager


class CustomUserManager(BaseUserManager):
    def _create_user(self, username, position, password, is_staff, is_superuser, **extra_fields):
        if not username:
            raise ValueError("Вы не ввели username!")
        if not password:
            raise ValueError("Вы не ввели пароль!")

        user = self.model(
            username=username,
            position=position,
            is_active=True,
            is_staff=is_staff,
            is_superuser=is_superuser,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, username, position="Администратор", password=None, **extra_fields):
        return self._create_user(username, position, password, is_staff=False, is_superuser=False, **extra_fields)

    def create_superuser(self, username, password=None, **extra_fields):
        return self._create_user(
            username,
            position="Главный администратор",
            password=password,
            is_staff=True,
            is_superuser=True,
            **extra_fields
        )

models.py

from django.contrib.auth.models import (
    AbstractBaseUser,
    PermissionsMixin,
)
from django.db import models
from .managers import CustomUserManager

POSITION = [
    ('Главный администратор', 'Главный администратор'),
    ('Администратор', 'Администратор'),
]

class User(AbstractBaseUser, PermissionsMixin):
    id = models.AutoField(primary_key=True, unique=True)
    username = models.CharField(max_length=24, unique=True, verbose_name="Имя пользователя (на английском)")
    position = models.CharField(choices=POSITION, default="Администратор", blank=False, null=False, max_length=21)
    is_active = models.BooleanField(default=True, verbose_name="Активность")
    is_staff = models.BooleanField(default=False, verbose_name="Администратор")
    is_superuser = models.BooleanField(default=False, verbose_name="Главный администратор")

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    class Meta:
        verbose_name = "Администратор"
        verbose_name_plural = "Администраторы"

    def __str__(self):
        return self.username

    def save(self, *args, **kwargs):
        if self.position == "Главный администратор":
            self.is_superuser = True
            self.is_staff = True
        elif self.position == "Администратор":
            self.is_superuser = False
            self.is_staff = True
        super().save(*args, **kwargs)

forms.py

from django import forms
from django.contrib.auth.forms import UserChangeForm
from .models import User


class CustomUserChangeForm(UserChangeForm):
    password = forms.CharField(
        widget=forms.PasswordInput(),
        required=False,
        help_text="Оставьте это поле пустым, если не хотите менять пароль."
    )

    class Meta:
        model = User
        fields = '__all__'

    def save(self, commit=True):
        user = super().save(commit=False)

        password = self.cleaned_data.get('password')
        if password:
            user.set_password(password)
        else:
            user.password = User.objects.get(id=user.id).password

        if commit:
            user.save()
        return user

admin.py

from django.contrib import admin
from .models import User
from .forms import CustomUserChangeForm

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    form = CustomUserChangeForm
    list_display = ('username', 'position')
    ordering = ('username',)

    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        ('Position', {'fields': ('position', )}),
    )

解决方案

1. 限制User模型的Admin访问权限

修改admin.py中的UserAdmin类,重写权限控制方法,仅允许超级管理员访问User模型:

from django.contrib import admin
from .models import User
from .forms import CustomUserChangeForm

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    form = CustomUserChangeForm
    list_display = ('username', 'position')
    ordering = ('username',)

    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        ('Position', {'fields': ('position', )}),
    )

    # 仅超级管理员能查看User模型
    def has_view_permission(self, request, obj=None):
        return request.user.is_superuser

    # 仅超级管理员能添加用户
    def has_add_permission(self, request):
        return request.user.is_superuser

    # 仅超级管理员能修改用户
    def has_change_permission(self, request, obj=None):
        return request.user.is_superuser

    # 仅超级管理员能删除用户
    def has_delete_permission(self, request, obj=None):
        return request.user.is_superuser

2. 给普通管理员分配其他模型权限

登录超级管理员账号,进入用户管理页面:

  • 找到目标普通管理员,进入用户详情页切换到「权限」标签
  • 手动勾选该用户需要操作的业务模型对应权限(如view_xxx、add_xxx、change_xxx、delete_xxx)
  • 或创建权限组,批量分配权限后将普通管理员加入组中

3. 验证效果

用普通管理员账号登录Django Admin:

  • 不会看到User模型入口
  • 可正常访问并操作已分配权限的业务模型
  • 不再出现权限不足的错误提示

内容的提问来源于stack exchange,提问作者Шахнур Калыбеков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 03:04:51