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

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

相关推荐
Jetev1 小时前
CSS如何实现复杂圣杯布局_结合flex布局与flex-basis轻松实现
jvm·数据库·python
大迪deblog1 小时前
系统架构设计-Redis设计-缓存穿透、缓存击穿、缓存雪崩
数据库·redis·系统架构
2401_867623981 小时前
HTML5中SVG解析器原理及手动构建矢量字符串
jvm·数据库·python
老纪1 小时前
Angular 表单中基于下拉选择动态启用字段必填校验的完整实现
jvm·数据库·python
weixin_459753941 小时前
Vue.js响应式shallowReadonly实现对象属性的一层状态保护
jvm·数据库·python
m0_470857641 小时前
uni-app怎么实现拖拽调整顺序 uni-app可拖动格子布局实现【技巧】
jvm·数据库·python
深蓝易网1 小时前
工厂目视化实操手册,告别形式主义
运维·网络·数据库·人工智能·汽车
dFObBIMmai1 小时前
MySQL如何利用存储过程封装权限_通过DEFINER与INVOKER模式控制
jvm·数据库·python
m0_748554811 小时前
如何用 stopPropagation 阻止事件冒泡防止触发父级回调
jvm·数据库·python