在Django Admin中按用户组限制Exam模型状态字段可选值
解决方案
要实现这个权限控制需求,我们可以通过重写Django Admin的get_form和save_model方法,结合用户组来动态限制状态选项并校验变更合法性,具体步骤如下:
1. 准备用户组与基础权限
首先在Django Admin后台创建两个用户组:X组和Y组,并为这两个组分配Exam模型的修改权限(即change_exam权限)。
2. 修改ExamAdmin代码
from django.core.exceptions import PermissionDenied from django.contrib import admin from your_app.models import Exam # 确保状态常量与模型中定义一致 PASS = 'PASS' FAILED = 'FAILED' GREAT = 'GREAT' @admin.register(Exam) class ExamAdmin(NestedModelAdmin): list_display = ('state',) def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) user_groups = request.user.groups.values_list('name', flat=True) # 仅处理编辑场景(新增场景需求未提及,默认保留默认状态逻辑) if obj: allowed_states = [] if 'X组' in user_groups: # X组仅能在当前状态为FAILED时修改为PASS,其他场景设为只读 if obj.state == FAILED: allowed_states = [PASS] else: form.base_fields['state'].widget.attrs['readonly'] = True elif 'Y组' in user_groups: # Y组可在FAILED时改PASS,PASS时改GREAT,其他场景设为只读 if obj.state == FAILED: allowed_states = [PASS] elif obj.state == PASS: allowed_states = [GREAT] else: form.base_fields['state'].widget.attrs['readonly'] = True # 过滤可选状态选项 if allowed_states: form.base_fields['state'].choices = [ (state, state) for state in allowed_states ] return form def save_model(self, request, obj, form, change): # 仅处理修改操作 if change: original_state = self.model.objects.get(pk=obj.pk).state new_state = obj.state user_groups = request.user.groups.values_list('name', flat=True) # 校验X组用户的状态变更合法性 if 'X组' in user_groups: if not (original_state == FAILED and new_state == PASS): raise PermissionDenied("你仅能将FAILED状态修改为PASS") # 校验Y组用户的状态变更合法性 elif 'Y组' in user_groups: valid_transitions = [(FAILED, PASS), (PASS, GREAT)] if (original_state, new_state) not in valid_transitions: raise PermissionDenied("你仅能将FAILED改为PASS,或PASS改为GREAT") super().save_model(request, obj, form, change)
方案说明
get_form方法:在生成编辑表单时,根据用户所在组和当前实例的状态,动态限制可选择的状态选项,非允许场景直接将状态字段设为只读,从前端层面限制操作。save_model方法:在保存实例前做最终校验,防止用户通过绕过前端表单的方式(如API调用、数据库直接修改)非法变更状态,从后端层面保障权限控制的安全性。
内容的提问来源于stack exchange,提问作者Mehdi Aria
相关产品推荐
相关产品推荐

