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

如何在Django REST Framework中自定义搜索过滤器,实现Bicycle列表查询学生姓名

实现方案

方案一(推荐:先规范模型关联关系)

你当前Bicycle模型的student_id是独立UUID字段,没有和Student模型建立关联,首先修改模型字段为外键,后续ORM跨表查询更便捷:

class Student(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    first_name = models.CharField(verbose_name=_('first name'), max_length=20, blank=True, null=True)
    last_name =models.CharField(verbose_name=_('last name'), max_length=20, blank=True, null=True)
        
class Bicycle(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    name = models.CharField(verbose_name=_('bicycle name'), max_length=20, blank=True, null=True)
    # 替换原有的student_id字段,db_column指定数据库字段名保持不变,不影响存量数据
    student = models.ForeignKey(Student, on_delete=models.CASCADE, db_column="student_id", related_name="bicycles")

修改完模型后执行python manage.py makemigrations、python manage.py migrate同步数据库结构。
之后直接修改视图的search_fields即可,DRF原生支持双下划线语法跨关联模型搜索:

class BicycleList(AdUpdateMixin, AdDestroyMixin, AdListMixin, AdCreateMixin, generics.GenericAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Bicycle.objects.all()
    # 新增跨Student表的搜索字段
    search_fields = ['name', 'id', 'student_id', 'student__first_name', 'student__last_name']

方案二(无需修改现有模型结构)

如果不想调整现有模型字段,可通过重写get_queryset方法自定义搜索逻辑,兼容Student姓名字段搜索:

from django.db.models import Q

class BicycleList(AdUpdateMixin, AdDestroyMixin, AdListMixin, AdCreateMixin, generics.GenericAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Bicycle.objects.all()
    search_fields = ['name', 'id', 'student_id']
    
    def get_queryset(self):
        queryset = super().get_queryset()
        search_word = self.request.query_params.get("search")
        if not search_word:
            return queryset
        # 先查询匹配姓名的Student主键列表
        match_stu_ids = Student.objects.filter(
            Q(first_name__icontains=search_word) | Q(last_name__icontains=search_word)
        ).values_list("id", flat=True)
        # 合并原搜索逻辑+学生姓名匹配逻辑
        return queryset.filter(
            Q(student_id__in=match_stu_ids) | 
            Q(name__icontains=search_word) |
            Q(id__icontains=search_word) |
            Q(student_id__icontains=search_word)
        )

注意事项

  • 方案一的外键迁移不会丢失存量数据,只要你现有student_id字段存储的都是合法的Student主键即可
  • 两种方案的搜索逻辑都和DRF原生搜索逻辑一致,为不区分大小写的模糊匹配

内容的提问来源于stack exchange,提问作者Võ Phú Hữu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 15:15:00