Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions app/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,19 @@ def _show_by_option(self, obj: NaturalPerson | None, option: str, detail: str):
return option, detail
return option

def _get_permission_display(self, obj: NaturalPerson | None, perm_key: str):
def _get_permission_display(self, request, obj: NaturalPerson | None, perm_key: str):
# 在新增表单(obj is None)时返回表单字段名;
# 在展示已存在对象时:如果当前用户有编辑权限则返回表单字段名,
# 否则返回只读展示方法名 `perm_<key>`。
if obj is None:
return perm_key
return perm_key
try:
if self.has_change_permission(request, obj):
return perm_key
except Exception:
# 如果调用方未传入 request 或出现异常,降级为只读展示
pass
return f'perm_{perm_key}'

def get_normal_fields(self, request, obj: NaturalPerson = None):
_m = NaturalPerson
Expand All @@ -116,7 +125,8 @@ def get_normal_fields(self, request, obj: NaturalPerson = None):
f(_m.accept_promote), f(_m.active_score),
])
for perm_config in PERMISSION_CONFIG:
fields.append(self._get_permission_display(obj, perm_config['key']))
fields.append(self._get_permission_display(
request, obj, perm_config['key']))
return fields

def get_student_fields(self, request, obj: NaturalPerson = None):
Expand Down Expand Up @@ -262,6 +272,28 @@ def _handle_permission(self, request, queryset, perm_key, grant):
if not perm_config:
return self.message_user(request=request, message='权限配置不存在!', level='error')

# 检查操作者是否有对应的权限检查方法或为超级用户
checker_name = f'has_{perm_key}_permission'
has_perm_fn = getattr(self, checker_name, None)
if has_perm_fn is None:
# 若未定义专门的权限检查,则仅允许超级用户操作
if not request.user.is_superuser:
return self.message_user(request=request,
message='操作失败,没有权限,请联系老师!',
level='warning')
else:
try:
if not has_perm_fn(request):
return self.message_user(request=request,
message='操作失败,没有权限,请联系老师!',
level='warning')
except TypeError:
# 兼容 has_*_permission 可能接受 (request, obj) 两种签名
if not has_perm_fn(request, None):
return self.message_user(request=request,
message='操作失败,没有权限,请联系老师!',
level='warning')

for person in queryset:
if grant:
person.grant_permission(perm_key)
Expand All @@ -271,18 +303,30 @@ def _handle_permission(self, request, queryset, perm_key, grant):
action = '赋予' if grant else '收回'
return self.message_user(request=request, message=f'修改成功!已{action}{perm_config["name"]}!')

# 为每个权限创建grant和revoke方法
# 为每个权限创建grant和revoke方法,并为动作添加权限检查与描述
for perm_config in PERMISSION_CONFIG:
perm_key = perm_config['key']

perm_name = perm_config.get('name', perm_key)

@as_action(f'赋予 {perm_name}', permissions=perm_key)
def grant_method(self, request, queryset, key=perm_key):
return self._handle_permission(request, queryset, key, True)


@as_action(f'收回 {perm_name}', permissions=perm_key)
def revoke_method(self, request, queryset, key=perm_key):
return self._handle_permission(request, queryset, key, False)

setattr(NaturalPersonAdmin, f'grant_{perm_key}', grant_method)
setattr(NaturalPersonAdmin, f'revoke_{perm_key}', revoke_method)
# 为每个权限创建只读显示方法
def _perm_display(self, obj, key=perm_key):
try:
return bool(obj.has_permission(key))
except Exception:
return False
_perm_display.short_description = perm_name
_perm_display.boolean = True
setattr(NaturalPersonAdmin, f'perm_{perm_key}', _perm_display)

@admin.register(Freshman)
class FreshmanAdmin(admin.ModelAdmin):
Expand Down