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

Django Admin与django-mptt-admin重写get_queryset不生效问题

问题排查:DjangoMpttAdmin重写get_queryset过滤无效,页面显示全部数据

可能原因及解决方案

1. Django-mptt-admin树渲染未复用get_queryset逻辑

部分版本的django-mptt-admin中,树状视图的渲染依赖专属的get_tree_queryset方法,而非默认的get_queryset。你重写的get_queryset仅会影响普通列表视图,树视图仍会拉取全部节点数据。

解决方法:同时重写get_tree_queryset方法,复用过滤逻辑:

class ContoCOGEAdmin(DjangoMpttAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        gruppo_id = request.session.get('gruppo_utente')
        if gruppo_id:
            return qs.filter(gruppo_id=int(gruppo_id))
        return qs

    # 新增重写树查询方法,复用过滤逻辑
    def get_tree_queryset(self, request):
        return self.get_queryset(request)

2. 缓存导致旧数据残留

浏览器缓存或Django的缓存中间件可能保留了未过滤的页面内容,导致新的过滤逻辑未生效。

解决方法:

  • 强制刷新浏览器页面(Ctrl+F5),清除浏览器缓存
  • 临时禁用admin站点的树结构永久缓存:
    class ContoCOGEAdmin(DjangoMpttAdmin):
        cache_tree_forever = False  # 禁用树结构缓存
        # ... 其他代码
    

3. Session值未正确传入Admin请求

尽管调试时确认Session存在,但Admin的请求上下文可能未正确携带gruppo_utente值(比如Admin登录会话与用户租户会话隔离)。

验证方法:在get_queryset中添加日志输出,确认Admin请求时的Session值:

import logging
logger = logging.getLogger(__name__)

class ContoCOGEAdmin(DjangoMpttAdmin):
    def get_queryset(self, request):
        logger.debug(f"Admin请求Session中的gruppo_utente: {request.session.get('gruppo_utente')}")
        qs = super().get_queryset(request)
        # ... 过滤逻辑

查看日志确认值是否存在且正确。

4. 超级用户权限绕过过滤

如果当前登录的是超级用户,部分Admin逻辑可能跳过自定义过滤规则(需排除此情况)。

解决方法:明确对所有用户(包括超级用户)应用租户过滤(如果业务需要):

def get_queryset(self, request):
    qs = super().get_queryset(request)
    gruppo_id = request.session.get('gruppo_utente')
    # 无论用户权限,只要Session有值就过滤
    if gruppo_id:
        return qs.filter(gruppo_id=int(gruppo_id))
    return qs

5. MPTT节点关联查询未过滤

如果自定义方法(如antenati或__str__)调用了get_ancestors(),默认情况下该方法会直接从数据库查询所有祖先节点,不会继承当前QuerySet的过滤条件。若数据存在跨租户的父子关联,可能间接导致无关节点被加载显示。

解决方法:在调用get_ancestors()时添加租户过滤:

def antenati(self):
    tmp=''
    if self.is_root_node():
        return format_html(f'<b> {} - {} </b>', mark_safe(self.nome), mark_safe(self.descrizione))
    # 过滤祖先节点属于当前租户
    ancestors = self.get_ancestors().filter(gruppo_id=self.gruppo_id)
    for i in ancestors:
        tmp += i.nome + '.'
    return tmp+self.nome+' - '+self.descrizione 

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 11:57:14