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

如何使用Django Filters按两个字段范围过滤模型数据?

用Django Filters实现年龄区间过滤

首先得先装好django-filter工具:

pip install django-filter

然后在项目的settings.py里把它加到INSTALLED_APPS:

INSTALLED_APPS = [
    # 其他已有的app
    'django_filters',
]

接下来分两种常见场景实现过滤:

场景1:根据单个年龄值筛选

比如用户输入年龄25,要找出所有min_age ≤25 ≤max_age的广告,同时兼容字段为空的情况(min_age为空表示无年龄下限,max_age为空表示无年龄上限)。

创建filters.py文件,定义过滤器类:

import django_filters
from .models import AdvertisementModelMixin

class AdvertisementFilter(django_filters.FilterSet):
    # 自定义一个age参数用来接收输入的年龄值
    age = django_filters.NumberFilter(method='filter_by_age_range')

    class Meta:
        model = AdvertisementModelMixin
        fields = ['age']

    def filter_by_age_range(self, queryset, name, value):
        # 构造过滤条件:满足年龄在广告的区间内,或区间无上下限
        return queryset.filter(
            django_filters.Q(min_age__lte=value) | django_filters.Q(min_age__isnull=True),
            django_filters.Q(max_age__gte=value) | django_filters.Q(max_age__isnull=True)
        )

在视图里使用这个过滤器,比如普通列表视图:

# views.py
from django.views.generic import ListView
from .models import AdvertisementModelMixin
from .filters import AdvertisementFilter

class AdvertisementListView(ListView):
    model = AdvertisementModelMixin
    template_name = 'advertisement_list.html'

    def get_queryset(self):
        queryset = super().get_queryset()
        # 用请求参数初始化过滤器,返回过滤后的查询集
        return AdvertisementFilter(self.request.GET, queryset=queryset).qs

前端只需要传/?age=25就能拿到符合条件的广告列表。

场景2:根据输入的年龄范围筛选

比如用户输入18到30,要找出所有和这个范围有交集的广告区间。

修改filters.py:

import django_filters
from .models import AdvertisementModelMixin

class AdvertisementFilter(django_filters.FilterSet):
    from_age = django_filters.NumberFilter(method='filter_by_age_range')
    to_age = django_filters.NumberFilter(method='filter_by_age_range')

    class Meta:
        model = AdvertisementModelMixin
        fields = ['from_age', 'to_age']

    def filter_by_age_range(self, queryset, name, value):
        from_age = self.request.GET.get('from_age')
        to_age = self.request.GET.get('to_age')

        if not from_age and not to_age:
            return queryset

        q = django_filters.Q()
        if from_age:
            # 广告的上限要大于等于输入的起始年龄,或广告无上限
            q &= django_filters.Q(max_age__gte=from_age) | django_filters.Q(max_age__isnull=True)
        if to_age:
            # 广告的下限要小于等于输入的结束年龄,或广告无下限
            q &= django_filters.Q(min_age__lte=to_age) | django_filters.Q(min_age__isnull=True)

        return queryset.filter(q)

前端传/?from_age=18&to_age=30就能得到符合条件的结果。

如果是用Django REST Framework,直接在视图集里配置过滤器即可:

# views.py(DRF)
from rest_framework import viewsets
from .models import AdvertisementModelMixin
from .serializers import AdvertisementSerializer
from .filters import AdvertisementFilter

class AdvertisementViewSet(viewsets.ModelViewSet):
    queryset = AdvertisementModelMixin.objects.all()
    serializer_class = AdvertisementSerializer
    filter_class = AdvertisementFilter

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 18:18:39