DRF 搜索功能实现

DjangoFilterBackend 真正强大的地方是:

  • 自定义 lookup
  • 支持 icontains
  • 支持 in
  • 支持区间
  • 支持时间范围
  • 支持组合查询

企业项目里一般都会配合:

python 复制代码
django-filter

和:

python 复制代码
FilterSet

来实现高级搜索。


一、安装

bash 复制代码
pip install django-filter

二、settings.py

python 复制代码
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend'
    ]
}

三、基础 FilterSet

模型:

python 复制代码
class User(models.Model):
    name = models.CharField(max_length=50)
    phone = models.CharField(max_length=20)
    status = models.IntegerField()
    created_at = models.DateTimeField(auto_now_add=True)

四、模糊搜索(icontains)

python 复制代码
import django_filters

class UserFilter(django_filters.FilterSet):

    name = django_filters.CharFilter(
        field_name='name',
        lookup_expr='icontains'
    )

    class Meta:
        model = User
        fields = ['name']

请求

python 复制代码
GET /api/users/?name=tom

SQL:

sql 复制代码
WHERE name LIKE '%tom%'

五、IN 查询(最常用)

例如:

python 复制代码
?id__in=1,2,3

写法

python 复制代码
class NumberInFilter(django_filters.BaseInFilter,
                     django_filters.NumberFilter):
    pass
python 复制代码
class UserFilter(django_filters.FilterSet):

    id__in = NumberInFilter(
        field_name='id',
        lookup_expr='in'
    )

    class Meta:
        model = User
        fields = []

请求

python 复制代码
GET /api/users/?id__in=1,2,3

SQL:

sql 复制代码
WHERE id IN (1,2,3)

六、多字段模糊搜索(企业最常见)

例如:

  • name
  • phone

都支持模糊。

python 复制代码
class UserFilter(django_filters.FilterSet):

    name = django_filters.CharFilter(
        lookup_expr='icontains'
    )

    phone = django_filters.CharFilter(
        lookup_expr='icontains'
    )

    class Meta:
        model = User
        fields = ['name', 'phone']

七、时间区间搜索

python 复制代码
created_at_after = django_filters.DateTimeFilter(
    field_name='created_at',
    lookup_expr='gte'
)

created_at_before = django_filters.DateTimeFilter(
    field_name='created_at',
    lookup_expr='lte'
)

请求:

python 复制代码
GET /api/users/?created_at_after=2025-01-01

八、完整企业版 FilterSet(推荐)

python 复制代码
import django_filters


class NumberInFilter(django_filters.BaseInFilter,
                     django_filters.NumberFilter):
    pass


class UserFilter(django_filters.FilterSet):

    # 模糊搜索
    name = django_filters.CharFilter(
        lookup_expr='icontains'
    )

    phone = django_filters.CharFilter(
        lookup_expr='icontains'
    )

    # IN 查询
    id__in = NumberInFilter(
        field_name='id',
        lookup_expr='in'
    )

    # 精确查询
    status = django_filters.NumberFilter()

    # 时间范围
    created_at_after = django_filters.DateTimeFilter(
        field_name='created_at',
        lookup_expr='gte'
    )

    created_at_before = django_filters.DateTimeFilter(
        field_name='created_at',
        lookup_expr='lte'
    )

    class Meta:
        model = User
        fields = []

九、ViewSet 配置

python 复制代码
from django_filters.rest_framework import DjangoFilterBackend

class UserViewSet(ModelViewSet):

    queryset = User.objects.all()
    serializer_class = UserSerializer

    filter_backends = [DjangoFilterBackend]

    filterset_class = UserFilter

十、支持的请求示例

模糊搜索

python 复制代码
GET /api/users/?name=tom

IN 查询

python 复制代码
GET /api/users/?id__in=1,2,3

多条件

python 复制代码
GET /api/users/?name=tom&status=1

时间范围

python 复制代码
GET /api/users/?created_at_after=2025-01-01

十一、企业项目最推荐方式

企业里通常:

python 复制代码
filter_backends = [
    DjangoFilterBackend,
    OrderingFilter,
]

不要用:

python 复制代码
SearchFilter

因为:

  • SearchFilter 太弱
  • 不好维护
  • 不支持复杂条件

真正企业级都是:

python 复制代码
FilterSet + lookup_expr

十二、更高级:自定义 OR 搜索

例如:

python 复制代码
keyword=tom

同时搜索:

  • name
  • phone

这个要自定义方法:

python 复制代码
from django.db.models import Q

class UserFilter(django_filters.FilterSet):

    keyword = django_filters.CharFilter(method='filter_keyword')

    def filter_keyword(self, queryset, name, value):
        return queryset.filter(
            Q(name__icontains=value) |
            Q(phone__icontains=value)
        )

    class Meta:
        model = User
        fields = []

请求:

python 复制代码
GET /api/users/?keyword=tom

这个是企业里最常见的"关键词搜索"。

相关推荐
Elastic 中国社区官方博客3 分钟前
如何比较两个 Elasticsearch 索引并找出缺失的文档
大数据·运维·数据库·elasticsearch·搜索引擎
DLYSB_16 分钟前
生命通道:如何用 HIS 医疗系统直连网络声光终端,打造“零延误”的危急值响应网关?
java·网络·数据库·报警灯
儒雅的大叔24 分钟前
MySQL数据库InnoDB数据恢复工具使用总结
数据库·mysql·adb
观远数据1 小时前
ChatBI选型对比:从意图识别到SQL修复,六个维度打分决定是否值得投产
数据库·人工智能·sql
嘉&年华1 小时前
【第008篇】通过dexp和dimp命令导出和导入dmp文件(适用于达梦数据库)
数据库·sql
哥是强混3 小时前
Means:基于 .NET 10 打造的开源自部署 S3 兼容对象存储服务
网络·数据库·.net
ffqws_3 小时前
redis面试:如何保证双写一致
数据库·redis·缓存
水无痕simon3 小时前
6 数据库同义词
数据库
杜子不疼.4 小时前
【Qt初识】信号槽(三):机制意义、断开连接与 Lambda 表达式
开发语言·数据库·qt
BomanGe15 小时前
NSK W1501FA高速精密滚珠丝杠技术手册
数据库·经验分享·规格说明书