Django DateFromToRange筛选器似乎不起作用

Django DateFromToRange筛选器似乎不起作用,django,django-filter,django-filters,Django,Django Filter,Django Filters,我有两个模型,其简单关系如下: models.py views.py 如图所示,我希望使用并期望得到如下api: api/persons?start_time_before=2018-04-20&start_time_after=2018-04-18 但这根本不起作用。正如本文所述,这种类型的过滤器的实现有一个错误,但本文中的解决方案对我不起作用,因为我会得到两个内部连接,并得到完全不同的结果 class PersonFilter(django_filters.FilterSet):

我有两个模型,其简单关系如下:

models.py views.py 如图所示,我希望使用并期望得到如下api:

api/persons?start_time_before=2018-04-20&start_time_after=2018-04-18
但这根本不起作用。正如本文所述,这种类型的过滤器的实现有一个错误,但本文中的解决方案对我不起作用,因为我会得到两个内部连接,并得到完全不同的结果

class PersonFilter(django_filters.FilterSet):
      start_time_before = DateFilter(name='person_sessions__start_time',lookup_expr=('gt'),) 
      start_time_after = DateFilter(name='person_sessions__start_time',lookup_expr=('lt'))

如果您想要相同的url,可以使用此类。

我也有同样的问题,我通过创建自定义筛选方法修复了它:

start_date = filters.CharFilter(
    method='filter_date_range'
)

def filter_date_range(self, queryset, name, value):
    filter_dict = {}
    splitted = value.split(',')

    if len(splitted) != 2:
        return queryset

    start = parse_date(splitted[0])
    end = parse_date(splitted[1])

    filter_dict[name + '__gte'] = start if start else datetime.date(2000, 1, 1)
    filter_dict[name + '__lt'] = end if end else datetime.date(2200, 1, 1)

    return queryset.filter(**filter_dict)

SQL: "app"."start_date" < 2018 - 01 - 10 AND "app"."start_date" >= 2000 - 01 - 01
start\u date=filters.CharFilter(
方法class='filter\u date\u range'
)
def过滤器\日期\范围(自身、查询集、名称、值):
筛选器_dict={}
拆分=值。拆分(','))
如果len(已拆分)!=2:
返回查询集
开始=解析日期(已拆分[0])
end=parse_date(拆分的[1])
filter_dict[name+'.\u gte']=start if start else datetime.date(2000,1,1)
filter_dict[name+'.\u lt']=end if end else datetime.date(2200,1,1)
返回queryset.filter(**filter\u dict)
SQL:“应用程序”“开始日期”<2018-01-10和“应用程序”“开始日期”>=2000-01-01

这是可以改进的,但至少它在WHERE子句中进行了直接检查,并将第一个值与T1进行比较,将第二个值与T2进行比较。

我也有类似的情况。也许对某些人会有帮助

class Task(ComputedFieldsModel):
    created_at = models.DateTimeField(auto_now_add=True)
    tco_at = models.DateTimeField(null=True, blank=True)

class TaskRangeStatisticsView(GenericAPIView):
    queryset = Task.objects.all()
    serializer_class = TaskRangeStatisticsSerializer
    filterset_class = TaskRangeStatisticsBackend

    def get(self,request):
        queryset = self.filter_queryset(self.get_queryset()) \
            .annotate(date=TruncDay('created_at')) \
            .values("date") \
            .annotate(finished_count=Count('tco_at'),created_count=Count('created_at'),in_progress_count=Count('in_progress_at')) \
            .order_by("-date")
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

class TaskRangeStatisticsBackend(df_filters.FilterSet):
    date = df_filters.DateFromToRangeFilter(field_name="created_at")
    # 'date_after': '2016-01-01', 'date_before': '2016-02-01'

    class Meta:
        model = Task
        fields = ["date"]

现在像
http://127.0.0.1:8000/api/v1/test_tasks_statistics/?date_after=2021-06-01&date\u before=2021-06-04
效果良好

api/人?开始时间\u 0=2018-04-20&start\u时间\u 1=2018-04-18此url与我提到的帖子类似,但我有两个问题,首先,它没有在文档中直接解释,其次,它非常模糊,我不理解之前和之后是什么,因为它们对我来说都有一个奇怪的结果。@amankumar使用_0表示gt,使用_1表示lt这一工作如预期,但正如我前面提到的,这是一个模糊和不恰当的过滤日期名称,我希望找到一种使用更好的名称约定的方法。请将您的过滤器类放在filters.py文件中,而不是放在views.py文件中!这实际上不适用于2个过滤器创建跨多对多连接的方式。这实际上意味着“x之前有一个会话或x之后有一个会话的人”。如果有2个会话与该用户关联,则可以复制此问题。这两个过滤器独立地加入到表中。
start_date = filters.CharFilter(
    method='filter_date_range'
)

def filter_date_range(self, queryset, name, value):
    filter_dict = {}
    splitted = value.split(',')

    if len(splitted) != 2:
        return queryset

    start = parse_date(splitted[0])
    end = parse_date(splitted[1])

    filter_dict[name + '__gte'] = start if start else datetime.date(2000, 1, 1)
    filter_dict[name + '__lt'] = end if end else datetime.date(2200, 1, 1)

    return queryset.filter(**filter_dict)

SQL: "app"."start_date" < 2018 - 01 - 10 AND "app"."start_date" >= 2000 - 01 - 01
class Task(ComputedFieldsModel):
    created_at = models.DateTimeField(auto_now_add=True)
    tco_at = models.DateTimeField(null=True, blank=True)

class TaskRangeStatisticsView(GenericAPIView):
    queryset = Task.objects.all()
    serializer_class = TaskRangeStatisticsSerializer
    filterset_class = TaskRangeStatisticsBackend

    def get(self,request):
        queryset = self.filter_queryset(self.get_queryset()) \
            .annotate(date=TruncDay('created_at')) \
            .values("date") \
            .annotate(finished_count=Count('tco_at'),created_count=Count('created_at'),in_progress_count=Count('in_progress_at')) \
            .order_by("-date")
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

class TaskRangeStatisticsBackend(df_filters.FilterSet):
    date = df_filters.DateFromToRangeFilter(field_name="created_at")
    # 'date_after': '2016-01-01', 'date_before': '2016-02-01'

    class Meta:
        model = Task
        fields = ["date"]