Django-filter: rest_framework.DateFilter(lookup_expr='lte') is not working as expected (doesn't get date exclusively despite 'lte' )

Created on 22 Dec 2019  ·  5Comments  ·  Source: carltongibson/django-filter

Using
django-filter==2.2.0
djangorestframework==3.10.3

Windows 10
DB: PostgreSQL 11.6

I wanted to filter by date on my submitted_at DateTime field so I made this

from django_filters import rest_framework

class DateRangeFilter(rest_framework.FilterSet):
    date_from = rest_framework.DateTimeFilter(
        field_name="submitted_at", lookup_expr='gte')
    date_to = rest_framework.DateTimeFilter(
        field_name="submitted_at", lookup_expr='lte')

    class Meta:
        fields = ['date_from', 'date_to']

It works fine for date_from as expected but for date_to it doesn't return the date exclusively as it supposes to do

for example:

https://?date_from=2019-01-04&date_to=2019-01-05

expected data

"line_chart_data": [
    {
      "submitted_at": "2019-01-05T18:10:49.811259+02:00",
      "answers": [
        {
          "question": 2,
          "choice": 4
        },
        {
          "question": 3,
          "choice": 4
        },
        {
          "question": 4,
          "choice": 4
        }
      ]
    },
    {
      "submitted_at": "2019-01-04T18:10:49.809389+02:00",
      "answers": [
        {
          "question": 2,
          "choice": 4
        },
        {
          "question": 3,
          "choice": 4
        },
        {
          "question": 4,
          "choice": 4
        }
      ]
    }]

https://?date_from=2019-01-04&date_to=2019-01-05

actual data:

  "line_chart_data": [
    {
      "submitted_at": "2019-01-04T18:10:49.809389+02:00",
      "answers": [
        {
          "question": 2,
          "choice": 4
        },
        {
          "question": 3,
          "choice": 4
        },
        {
          "question": 4,
          "choice": 4
        }
      ]
    }]

and that's a bit odd, as if something is wrong it should not work at all not only for date_to unless there is some reason

I know I'm giving it only dates but no warning was in the console and everything was just ok

Most helpful comment

@dalvtor is correct that you should use the date transform, however the code should look like:

class DateRangeFilter(FilterSet):
    date_from = DateFilter(field_name='submitted_at', lookup_expr='date__gte')

field_name should always map to the model field name. lookup_expr should handle lookups & transforms.

All 5 comments

This is not a bug. Change your DateRangeFilter filter to the following so it works like you would expect:

class DateRangeFilter(rest_framework.FilterSet):
    date_from = rest_framework.DateTimeFilter(
        field_name="submitted_at__date", lookup_expr='gte')
    date_to = rest_framework.DateTimeFilter(
        field_name="submitted_at__date", lookup_expr='lte')

    class Meta:
        fields = ['date_from', 'date_to']

Notice the __date after your field names.

The reason after this is that you need to extract the date from your DateTimeField so the filter operation (lte) can be performed between date and date, not between date and datetime

@dalvtor is correct that you should use the date transform, however the code should look like:

class DateRangeFilter(FilterSet):
    date_from = DateFilter(field_name='submitted_at', lookup_expr='date__gte')

field_name should always map to the model field name. lookup_expr should handle lookups & transforms.

Just got bit by the same issue. The workaround @rpkilby suggests does indeed work but it's not intuitive, if you use a DateFilter you certainly would expect the lte comparison is against the date.

Maybe we could at least add this to the documentation of DateFilter if we can't fix it in a good way?

Of course thanks to @rpkilby for his answer it showed me the right way to take, but @bwesen That's what I was talking about!

Just to contribute, I had the same problems with DateFilter and DateFromToRangeFilter today. Turns out I was passing nonexistent dates (For example, sending the day part of the date as 31st when the month only had 30 days). After making sure the day part was according to each month, worked like a breeze.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sassanh picture sassanh  ·  4Comments

madelyneriksen picture madelyneriksen  ·  4Comments

gsvr picture gsvr  ·  3Comments

xtrinch picture xtrinch  ·  4Comments

csarcom picture csarcom  ·  3Comments