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

