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

Django自定义UserAdmin设置权限时触发KeyError问题求助

Django Admin权限控制KeyError问题解决

问题概述

我是Python/Django初学者,想在CustomUserAdmin中实现权限控制:仅超级管理员可修改is_superuser、user_permissions、groups字段,普通用户/Staff用户登录时这些字段置灰。添加该逻辑前admin.py运行正常,但新增用户时触发KeyError,提示'is_superuser'不存在。

报错信息

KeyError at /admin/people/customuser/add/

'is_superuser'

Request Method:     GET
Request URL:    http://localhost:8000/admin/people/customuser/add/
Django Version:     4.1.5
Exception Type:     KeyError
Exception Value:    

'is_superuser'

Exception Location:     /cpp_base/people/admin.py, line 25, in get_form
Raised during:  django.contrib.auth.admin.add_view
Python Executable:  /usr/local/bin/python
Python Version:     3.10.4

相关代码

admin.py代码片段

from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import JobTitle, JobSkill, SkillSet


CustomUser = get_user_model()

@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
    # 实现权限控制逻辑
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        is_superuser = request.user.is_superuser

        if not is_superuser:
            form.base_fields["is_superuser"].disabled = True
            form.base_fields["user_permissions"].disabled = True
            form.base_fields["groups"].disabled = True
        return form

    add_form = CustomUserCreationForm
    form = CustomUserChangeForm
    model = CustomUser
    readonly_fields = ["last_login", "date_joined"]
    list_display = [
        "username",
        "employed",
        "email",
        "job_title",
        "is_active",
        "is_staff",
        "is_superuser",
    ]

    fieldsets = (
        (
            None,
            {
                "fields": (
                    "username",
                    "password",
                    "first_name",
                    "last_name",
                )
            },
        ),
        (
            "Persönliche Information",
            {
                "fields": ("birth_date", "employed", "job_title", "skill_set"),
            },
        ),
        (
            "Adresse und Kontakt",
            {
                "classes": ("collapse",),
                "fields": (
                    "email",
                    "mobile_number",
                    "phone_number",
                    "street_name",
                    "street_number",
                    "zip_code",
                    "city",
                    "country",
                ),
            },
        ),
        (
            "Berechtigungen",
            {
                "classes": ("collapse",),
                "fields": (
                    "is_active",
                    "is_staff",
                    "is_superuser",
                    "groups",
                    "user_permissions",
                ),
            },
        ),
        (
            "Anmelde Daten",
            {
                "classes": ("collapse",),
                "fields": (
                    "last_login",
                    "date_joined",
                ),
            },
        ),
    )


class JobTitleAdmin(admin.ModelAdmin):
    readonly_fields = ("created_at", "updated_at")


admin.site.register(JobTitle, JobTitleAdmin)
admin.site.register(JobSkill)
admin.site.register(SkillSet)

表单代码

from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm, UserChangeForm


class CustomUserCreationForm(UserCreationForm):
    class Meta:
        model = get_user_model()
        fields = (
            "username",
            "email",
            "birth_date",
            "mobile_number",
            "phone_number",
            "job_title",
            "skill_set",
        )


class CustomUserChangeForm(UserChangeForm):
    class Meta:
        model = get_user_model()
        fields = (
            "username",
            "email",
            "birth_date",
            "mobile_number",
            "phone_number",
            "job_title",
            "skill_set",
        )

问题原因

新增用户时,Django使用的是CustomUserCreationForm,而这个表单的Meta.fields里并没有包含is_superuser、groups、user_permissions这些字段,所以form.base_fields字典里不存在这些键,直接访问就会抛出KeyError。

解决方案

修改get_form方法,要么判断字段是否存在,要么仅在编辑用户(obj不为None)的场景下处理权限字段:

方案一:先检查字段是否存在

def get_form(self, request, obj=None, **kwargs):
    form = super().get_form(request, obj, **kwargs)
    is_superuser = request.user.is_superuser

    if not is_superuser:
        # 遍历字段,仅存在时设置禁用
        for field_name in ["is_superuser", "user_permissions", "groups"]:
            if field_name in form.base_fields:
                form.base_fields[field_name].disabled = True
    return form

方案二:仅在编辑用户时处理

因为新增用户页面本来就不会显示这些权限字段,所以只需要在编辑用户时禁用:

def get_form(self, request, obj=None, **kwargs):
    form = super().get_form(request, obj, **kwargs)
    is_superuser = request.user.is_superuser

    # 只有编辑用户且当前用户不是超级管理员时,才禁用字段
    if not is_superuser and obj is not None:
        form.base_fields["is_superuser"].disabled = True
        form.base_fields["user_permissions"].disabled = True
        form.base_fields["groups"].disabled = True
    return form

两种方案都能解决KeyError问题,同时实现预期的权限控制效果。

内容的提问来源于stack exchange,提问作者gomez_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:30:43