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

Django中如何在渲染前过滤模型Queryset并向utils传递用户信息

你重写的get_queryset不生效的核心原因是:utils.py中的Calendar类的formatmonth方法直接硬编码查询了Class模型,完全没有使用ListView过滤后的数据集,所以不管你怎么修改get_queryset,日历渲染时都会走独立的全量查询逻辑。


解决方案

实现思路

将数据过滤逻辑全部移到视图层处理,过滤完成后再把结果传给Calendar类做渲染,既可以直接调用self.request.user做身份过滤,也符合Django分层设计的规范。

步骤1:修改utils.py中的Calendar类

删除formatmonth方法中硬编码的查询逻辑,改为接收外部传入的events参数:

# utils.py
class Calendar(HTMLCalendar):
    # 保留其他原有方法不变
    def formatmonth(self, events, withyear=True):
        # 删除原来的events = Class.objects.filter(...)那行代码
        cal = f'<table border="0" cellpadding="0" cellspacing="0" class="calendar">\n'
        cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n'
        cal += f'{self.formatweekheader()}\n'
        for week in self.monthdays2calendar(self.year, self.month):
            cal += f'{self.formatweek(week, events)}\n'
        return cal

步骤2:修改视图逻辑,完成身份过滤后传参

在视图的get_queryset中完成用户身份、月份的过滤,再把结果传给formatmonth方法:

# views.py
class CalendarView(LoginRequiredMixin, generic.ListView):
    model = Class
    template_name = 'leads/calendar.html'

    def get_queryset(self):
        base_queryset = super().get_queryset()
        # 获取当前登录用户
        current_user = self.request.user
        # 按用户身份过滤,示例逻辑可自行修改
        if current_user.is_student:
            base_queryset = base_queryset.filter(student=current_user)
        elif current_user.is_teacher:
            base_queryset = base_queryset.filter(teacher=current_user)
        # 按当前查询的月份过滤
        d = get_date(self.request.GET.get('month', None))
        base_queryset = base_queryset.filter(
            date__year=d.year, 
            date__month=d.month
        ).exclude(student=None)
        return base_queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        d = get_date(self.request.GET.get('month', None))
        cal = Calendar(d.year, d.month)
        # 把过滤好的课程数据传给日历渲染方法
        html_cal = cal.formatmonth(events=self.get_queryset(), withyear=True)
        context['calendar'] = mark_safe(html_cal)
        context['prev_month'] = prev_month(d)
        context['next_month'] = next_month(d)
        return context

补充说明

模板代码不需要做任何修改,原有逻辑可以直接复用。如果后续需要调整过滤规则,只需要修改视图层的get_queryset方法即可,不需要改动工具类的渲染逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 08:57:00