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

Django BaseDataTableView的filter_queryset方法失效问题求助

问题分析与修复方案

核心问题

你重写了get和get_json_response方法,完全跳过了BaseDatatableView内置的查询集处理流程——原本框架会自动调用filter_queryset对初始查询集进行过滤,再处理分页,但你的自定义实现直接使用get_initial_queryset(),根本没触发filter_queryset,所以搜索过滤完全失效,print('test')自然不会输出。

另外render_column方法里的super调用写错了,应该是super(MyModelDatatable, self),不是OrderDatatable。

修复方案

方案一:移除自定义的get和get_json_response方法

BaseDatatableView已经实现了完整的服务端处理逻辑(过滤、分页、计数),你不需要自己重写这些方法。只保留prepare_results、render_column、filter_queryset和get_initial_queryset即可。

修改后的views.py:

class MyModelDatatable(BaseDatatableView):
    model = MyModel
    columns = ['field1', 'field2', 'id']
    columns_searched = [col for col in columns if col != 'id']
    
    def get_initial_queryset(self):
        return self.model.objects.all()

    def filter_queryset(self, qs):
        print('test')  # 现在会正常输出
        search_text = self.request.GET.get('search[value]', None)
        if search_text:
            search_terms = search_text.split()
            query = Q()

            for col in self.columns_searched:
                or_conditions = Q()

                for term in search_terms:
                    or_conditions |= Q(**{f'{col}__icontains': term})

                query |= or_conditions    

            qs = qs.filter(query)

        return qs

    def prepare_results(self, qs):
        data = []
        for item in qs:
            item_str = str(item)
            data.append({
                'field1': item_str,
                'field2': item.field2,
                'id': item.id
            })
        return data

    def render_column(self, row, column):
        if column == 'field2':
            return row.field2.strftime('%Y-%m-%d')
        return super(MyModelDatatable, self).render_column(row, column)

方案二:如果必须保留自定义响应逻辑,修正get_json_response

如果你需要自定义响应格式,必须在方法中正确调用filter_queryset,并计算过滤后的记录数:

class MyModelDatatable(BaseDatatableView):
    model = MyModel
    columns = ['field1', 'field2', 'id']
    columns_searched = [col for col in columns if col != 'id']
    
    def get_initial_queryset(self):
        return self.model.objects.all()

    def filter_queryset(self, qs):
        print('test')  # 现在会正常输出
        search_text = self.request.GET.get('search[value]', None)
        if search_text:
            search_terms = search_text.split()
            query = Q()

            for col in self.columns_searched:
                or_conditions = Q()

                for term in search_terms:
                    or_conditions |= Q(**{f'{col}__icontains': term})

                query |= or_conditions    

            qs = qs.filter(query)

        return qs

    def prepare_results(self, qs):
        data = []
        for item in qs:
            item_str = str(item)
            data.append({
                'field1': item_str,
                'field2': item.field2,
                'id': item.id
            })
        return data

    def render_column(self, row, column):
        if column == 'field2':
            return row.field2.strftime('%Y-%m-%d')
        return super(MyModelDatatable, self).render_column(row, column)

    def get(self, request, *args, **kwargs):
        return self.get_json_response()

    def get_json_response(self):
        draw = int(self.request.GET.get('draw', 1))
        initial_qs = self.get_initial_queryset()
        # 调用filter_queryset处理搜索过滤
        filtered_qs = self.filter_queryset(initial_qs)
        total_records = initial_qs.count()
        # 过滤后的记录数应该用filtered_qs的计数
        total_display_records = filtered_qs.count()
        start = int(self.request.GET.get('start', 0))
        length = int(self.request.GET.get('length', 10))
        # 对过滤后的查询集进行分页
        paginated_qs = filtered_qs[start:start+length]
        data = self.prepare_results(paginated_qs)
        response = {
            'draw': draw,
            'recordsTotal': total_records,
            'recordsFiltered': total_display_records,
            'data': data,
        }
        return JsonResponse(response)

额外注意事项

  • 确保columns_searched里的字段都是模型中存在的可搜索字段,避免查询报错。
  • 前端DataTable配置的serverSide: true是正确的,保持不变即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 16:28:18