'How to filter in django by greater than or less than dates?

I'm a little confused with the documentation on Django Rest Framework. I have read it several times but I cannot makes sense of it. Maybe I'm not smart enough, I do not know, but I'm trying to create a filter in an Endpoint that let me consult information according to dates, like

GET /my-endpoint/?created_at__lte=2020-01-01 // get items created in a date less than 2020-01-01

GET /my-endpoint/?created_at__gte=2020-01-01  // get items created in a date greater than 2020-01-01

I created a filter class

class MyEndpointFilter(django_filters.rest_framework.FilterSet):
    created_at_gte = IsoDateTimeFilter(field_name="created_at", lookup_expr='gte')
    created_at_lte = IsoDateTimeFilter(field_name='created_at', lookup_expr='lte')

    updated_at_gte = IsoDateTimeFilter(field_name='updated_at', lookup_expr='gte')
    updated_at_lte = IsoDateTimeFilter(field_name='updated_at', lookup_expr='lte')

    class Meta:
        model = MyEndpointModel
        fields = (
            'created_at',
            'updated_at',
        )

And a class view

class MyEndpointViewSet(viewsets.ReadOnlyModelViewSet):
   
    filter_backends = (
        django_filters.rest_framework.DjangoFilterBackend, OrderingFilter
    )
    filterset_class = MyEndpointFilter
    filterset_fields = {'created_at': ['gte', 'lte'], 'updated_at': ['gte', 'lte']} # I also tried without this line
    queryset = LogClaimAction.objects.all()
    serializer_class = MyEndPointSerializer

But still, the filter doesn't work. Can someone point me to the mistake I am making?



Solution 1:[1]

You can use django_filters.FilterSet instead of django_filters.rest_framework.FilterSet in your filterset_class and make your filterset_fields a list instead of dict.

import django_filters

...

class MyEndpointFilter(django_filters.FilterSet):
    created_at_gte = IsoDateTimeFilter(field_name="created_at", lookup_expr='gte')
    created_at_lte = IsoDateTimeFilter(field_name='created_at', lookup_expr='lte')

    updated_at_gte = IsoDateTimeFilter(field_name='updated_at', lookup_expr='gte')
    updated_at_lte = IsoDateTimeFilter(field_name='updated_at', lookup_expr='lte')

    class Meta:
        model = MyEndpointModel
        fields = '__all__'
from django_filters.rest_framework import DjangoFilterBackend, OrderingFilter

...

class MyEndpointViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = LogClaimAction.objects.all()
    serializer_class = MyEndPointSerializer
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    filterset_class = MyEndpointFilter
    filterset_fields = ['created_at_gte', 'created_at_lte', 'updated_at_gte', 'updated_at_lte']

Testing

GET /my-endpoint/?created_at_lte=2020-02-02
GET /my-endpoint/?created_at_gte=2020-01-01
GET /my-endpoint/?created_at_lte=2020-02-02&created_at_gte=2020-01-01

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ged Flod