Django REST framework range filter
Asked Answered
J

2

8

How can I do a range filter for dates and number in Django REST Framework? Other filters (lt, gt etc.) work fine. I tried many variants such as:

import rest_framework_filters as filters

class OrderFilter(filters.FilterSet):
    total_price__range = filters.RangeFilter(name='total_price')
    created_at__range = filters.DateFromToRangeFilter(name='created_at')
    ....
    class Meta:
        model = Order

        fields = {
            'created_at__range': ['__all__'],
            'total_price__range': ['__all__'],
            ...
            }

class OrderViewSet(BaseViewSet, viewsets.ModelViewSet):
    filter_class = OrderFilter
    ....

In the browsable api there are to fields when I click on bottom "Filters", Then url looks like:

/orders/?created_at__range_0=2017-05-22&created_at__range_1=2017-05-22

and it doesn't work. I need something like

/orders/?created_at__range=2017-05-22,2017-05-24

and same with integer:

/orders/?total_price__range=1000,2000

It was described here .

What am I doing wrong?

Jennelljenner answered 25/5, 2017 at 13:38 Comment(0)
L
7

First, you've got total_price as your field name but you're URL says total_cost.

Second, remove the __range suffix from your filter names. Anything with __ is part of the Django filtering. For example, if you were querying a model in Django for a value greater than something you'd do:

MyModel.objects.filter(price__gte=50)

Note the __gte suffix; That's how Django does filter modifiers. So your class should be something like:

class OrderFilter(filters.FilterSet):
    total_price = filters.RangeFilter(name='total_price')
    # ...

Then you can apply range filtering on that field in the query.

Lento answered 25/5, 2017 at 13:49 Comment(2)
Thank you for so fast reply and revision. There is no total_cost, only total_price, my error. Now I tried: total_price = filters.RangeFilter(name='total_price') but in this case is possible to do only request with params, that doesn't works. /orders/?total_price_0=1000&total_price_1=5000 Is possible to do request like: /orders/?total_price_range=1000,5000 ?Jennelljenner
github.com/philipn/… - here is described why it desnt' works... possible sollution: "Use a CSV-based filter such as those derived from BaseCSVFilter/BaseInFilter/BaseRangeFilter" How can I use it?Jennelljenner
S
1

For your URL format /orders/?created_at__range=2017-05-22,2017-05-24

for date ranges and /orders/?total_price__range=1000,2000.

for number ranges

import rest_framework_filters as filters

class OrderFilter(filters.FilterSet):
    total_price__range = filters.RangeFilter(field_name='total_price')
    
    # For date range filtering
    created_at__range = filters.DateFromToRangeFilter(field_name='created_at')

    class Meta:
        model = Order
        fields = {
            'created_at__range': ['exact', 'lt', 'gt'],  # Include additional filters if needed
            'total_price__range': ['exact', 'lt', 'gt'],  # Include additional filters if needed
           
        }
Sandwich answered 15/4, 2024 at 9:27 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.