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

React调用Django DRF API实现多条件过滤及分页方案咨询

问题

我有一个调用Django REST Framework(DRF)API的React应用,希望在前端设置多条件过滤,从API获取带过滤条件的分页数据,该如何构造请求?

当前我的views.py中ExerciseView继承ModelViewSet,代码如下:

from .serializer import ExerciseSerializer
from rest_framework import viewsets
from rest_framework.pagination import PageNumberPagination

class ExerciseView(viewsets.ModelViewSet):
    serializer_class = ExerciseSerializer
    queryset = Exercise.objects.all()
    pagination_class = PaginateExercises

我知道可以通过queryset = Exercise.objects.all().filter(course="Precalculus")实现固定条件过滤,但需要支持前端动态传递多个过滤条件。尝试重写get_queryset方法:

def get_queryset(self) -> QuerySet[Any]:
    course = self.kwargs['course']
    return Exercise.objects.all().filter(course=course)

但终端报错KeyError: 'course',重写get方法也未成功。前端已通过axios的get请求传递参数,代码如下:

import axios from "axios";

const exerciseAPI = axios.create({
    baseURL: "http://localhost:8000/exercises/api/exercise/",
});

export const getAllExercises = (
    pagenum = 1,
    course = "",
    lesson = "",
    topic = ""
) => {
    return exerciseAPI.get("/", {
        params: { page: pagenum, course: course, lesson: lesson, topic: topic },
    });
};

请问后端如何获取这些参数并实现动态多条件过滤,或有无更优解决方案?


解决方案

1. 正确获取前端参数

你之前用self.kwargs['course']报错,是因为kwargs用于读取URL路径中的参数(比如/exercises/<course>/结构里的course),而前端是通过URL查询参数(即?course=xxx&lesson=xxx格式)传递数据,应该用self.request.query_params来获取。

2. 手动实现动态多条件过滤

重写get_queryset方法,从查询参数中提取非空条件并逐个应用:

from django.db.models import QuerySet
from rest_framework import viewsets

class ExerciseView(viewsets.ModelViewSet):
    serializer_class = ExerciseSerializer
    queryset = Exercise.objects.all()
    pagination_class = PaginateExercises

    def get_queryset(self) -> QuerySet:
        queryset = super().get_queryset()
        
        # 从请求中提取过滤参数
        course = self.request.query_params.get('course')
        lesson = self.request.query_params.get('lesson')
        topic = self.request.query_params.get('topic')
        
        # 仅当参数不为空时添加过滤规则
        if course:
            queryset = queryset.filter(course=course)
        if lesson:
            queryset = queryset.filter(lesson=lesson)
        if topic:
            queryset = queryset.filter(topic=topic)
        
        return queryset

这种方式逻辑简单直接,适合基础的等值过滤场景。

3. 更优方案:使用DRF集成的FilterSet

如果需要扩展模糊匹配、范围查询等复杂过滤逻辑,推荐使用django-filter库,它和DRF深度集成,无需手动编写大量过滤代码:

步骤1:安装依赖

pip install django-filter

步骤2:配置项目settings.py

在INSTALLED_APPS中添加应用,并配置DRF的过滤器后端:

INSTALLED_APPS = [
    # ...其他已有应用
    'django_filters',
]

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
    ],
}

步骤3:定义FilterSet规则

在应用目录下创建filters.py,指定允许过滤的字段和规则:

import django_filters
from .models import Exercise

class ExerciseFilter(django_filters.FilterSet):
    # 可自定义过滤规则,比如忽略大小写的模糊匹配
    # course = django_filters.CharFilter(lookup_expr='icontains')
    class Meta:
        model = Exercise
        fields = ['course', 'lesson', 'topic']  # 指定支持过滤的字段

步骤4:在ViewSet中启用FilterSet

修改ExerciseView,添加filterset_class配置:

from .filters import ExerciseFilter
from rest_framework import viewsets

class ExerciseView(viewsets.ModelViewSet):
    serializer_class = ExerciseSerializer
    queryset = Exercise.objects.all()
    pagination_class = PaginateExercises
    filterset_class = ExerciseFilter

配置完成后,DRF会自动处理前端传递的查询参数,同时支持快速扩展复杂过滤逻辑。

前端请求说明

你当前的axios代码已经正确,params会自动拼接为URL查询参数(比如?page=1&course=Precalculus),和后端两种实现方案都兼容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:23:10