如何配置Django FilterSet使结束日期筛选取当日23:59而非00:00?
解决Django FilterSet日期筛选的结束日期问题
嘿,这个问题我之前也碰到过!Django FilterSet的DateFilter默认会把传入的日期解析成当天的00:00:00,所以用lte匹配结束日期的时候,自然就漏掉了当天的所有数据。给你几个实用的解决方案:
方案一:自定义结束日期Filter类(可复用)
如果你的项目里多个地方需要这种“结束日期取当日23:59”的逻辑,自定义一个Filter类是最方便的,后续可以直接复用:
from django_filters import DateFilter from datetime import datetime class EndDateFilter(DateFilter): def filter(self, qs, value): if value: # 将传入的日期转换为当天的23:59:59 end_datetime = datetime.combine(value, datetime.max.time()) return qs.filter(**{f'{self.field_name}__lte': end_datetime}) # 如果没有传入值,直接返回原查询集 return qs
然后修改你的TaskFilterSet,把原来的end_filter_date替换成这个自定义Filter:
class TaskFilterSet(django_filters.rest_framework.FilterSet): id = django_filters.NumberFilter(name="pk") start_filter_date = django_filters.DateFilter(name="date_added", lookup_expr="gte") # 使用自定义的EndDateFilter end_filter_date = EndDateFilter(name="date_added")
方案二:在FilterSet中用method直接处理(快速实现)
如果只是当前FilterSet需要这个逻辑,直接用method参数绑定一个处理函数更直接:
from django_filters.rest_framework import FilterSet, DateFilter from datetime import datetime class TaskFilterSet(FilterSet): id = DateFilter(name="pk") start_filter_date = DateFilter(name="date_added", lookup_expr="gte") # 绑定处理结束日期的方法 end_filter_date = DateFilter(name="date_added", method="handle_end_date") def handle_end_date(self, queryset, name, value): if value: end_datetime = datetime.combine(value, datetime.max.time()) return queryset.filter(**{f'{name}__lte': end_datetime}) return queryset
方案三:换一种查询逻辑(更简洁)
还有个更巧妙的思路:把结束日期的查询条件改成lt(小于),然后将传入的日期加一天。这样lt 2018-05-26 00:00:00就等价于lte 2018-05-25 23:59:59,代码更简洁:
from django_filters.rest_framework import FilterSet, DateFilter from datetime import timedelta class TaskFilterSet(FilterSet): id = DateFilter(name="pk") start_filter_date = DateFilter(name="date_added", lookup_expr="gte") end_filter_date = DateFilter(name="date_added", method="handle_end_date") def handle_end_date(self, queryset, name, value): if value: next_day = value + timedelta(days=1) return queryset.filter(**{f'{name}__lt': next_day}) return queryset
这三种方法都能解决你的问题,根据你的实际场景选就行~
内容的提问来源于stack exchange,提问作者Konstantin
相关产品推荐
相关产品推荐

