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

Django Admin变更列表页list_display显示异常问题求助

问题分析与解决方案

这个问题的核心原因其实是Django的Admin类是全局单例对象,你直接在changelist_view里修改self.list_display会影响所有后续请求,这才导致超级用户的字段显示来回切换。

具体问题拆解

  1. 单例属性共享干扰
    当你修改self.list_display时,你是在修改这个Admin类实例的全局属性。比如第一个请求是普通用户,你把list_display改成了短版本;接下来的超级用户请求会直接继承这个修改后的属性,直到另一个超级用户请求把它改回长版本——这就是为什么你看到“几乎有一半时间切换”的现象,完全取决于上一个请求的用户类型。

  2. 超级用户权限的误解
    Django里超级用户的has_perm()方法始终返回True,不管有没有给这个用户或其组设置对应权限。所以你的原条件if user.has_perm('some_app.perm1')对超级用户来说也是成立的,这会让超级用户偶尔进入普通用户的分支,但核心问题还是单例属性被共享修改的问题。

正确解决方案:重写get_list_display方法

不要直接修改Admin实例的list_display,而是重写Django提供的get_list_display方法——这个方法就是专门用来动态返回当前用户对应字段列表的,每个请求都会独立调用,不会干扰其他用户。

class CustomAdmin(admin.ModelAdmin):
    # 设置默认字段作为 fallback
    list_display = ('field1', 'field2', 'field3', 'field4',)

    def get_list_display(self, request):
        user = request.user
        # 先判断是否为超级用户,再校验普通用户的权限
        if not user.is_superuser and user.has_perm('some_app.perm1'):
            make_log('non-super user')
            return ('field1', 'field2',)
        else:
            make_log('superuser')
            return ('field1', 'field2', 'field3', 'field4',)

效果说明

  • 每个请求都会根据当前用户的身份返回对应的字段列表,不会修改全局的list_display属性
  • 超级用户会始终看到完整的4个字段,拥有perm1权限的普通用户始终看到2个字段
  • 日志也会准确记录每个请求的用户类型,不会出现混乱

这个方式是Django官方推荐的实现动态字段的方案,既安全又符合框架的设计逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:01:51