daterange on a django-filter

enter_thevoid picture enter_thevoid · May 21, 2015 · Viewed 19k times · Source

I use Django, the Django REST Framework plus django-filters (alex/django-filter).

I have a model with the fields start_date and end_date and I'm trying to build a date api-endpoint which should receive a date and respond with items where (start_date < date) and (end_date > date). There is a DateRangeFilter but I can't figure out how to use it. Here is my code so far:

urls.py:

url(r'^api/sales/$', views.SaleItemList.as_view(), name='sales'),

views.py:

class SaleItemFilter(django_filters.FilterSet):
    city = django_filters.CharFilter(name='trade_item__vendor__city')
    title = django_filters.CharFilter(name='trade_item__title')
    date = django_filters.DateRangeFilter()

    class Meta:
        model = SaleItem
        fields = ['sale_price', 'sale_date_start', 'sale_date_end', 'trade_item']

class SaleItemList(generics.ListAPIView):
    queryset = SaleItem.objects.all()
    serializer_class = SaleItemListSerializer
    filter_class = SaleItemFilter

serializers.py:

class SaleItemListSerializer(serializers.ModelSerializer):
    class Meta:
        model = SaleItem
        fields = ("sale_price", "sale_date_start", "sale_date_end", "trade_item", "slogan")

I can filter for exact dates so far:

/api/sales/?sale_date_start=2015-05-22

Answer

ksi_help picture ksi_help · Jun 12, 2015

I can't speak to the Django REST Framework part of your question, but I hope I can lend some insight to the django-filter part!

If you use a DateRangeFilter, the result would be a dropdown with the options "any date", "today", "past 7 days", "this month" and "this year".

If your variable is 'date', either of these will give you a date range with the label "Date Range":

date_range = DateRangeFilter(field_name='date')
date = DateRangeFilter(label='Date_Range')

The difference is that if you use the first one, you can use your variable "date" again, so you could give your user the choice to filter by start date, end date, or both (to get dates between), all using the same date variable.

(You can only use "date" to the left of the equal sign one time (or not at all)).

To get the start and end date, do:

start_date = DateFilter(field_name='date',lookup_expr=('lt'),) 
end_date = DateFilter(field_name='date',lookup_expr=('gt'))

You don't need to call "date" again in Meta, but you can. You do need to call something. It could be your date, or some other field you want to filter.

Here is a full code and screenshot example:

from django_filters import DateRangeFilter,DateFilter
from wesapp.models import MyModel

class SaleItemFilter(django_filters.FilterSet):
    start_date = DateFilter(name='date',lookup_type=('gt'),) 
    end_date = DateFilter(name='date',lookup_type=('lt'))
    date_range = DateRangeFilter(name='date')

    class Meta:
        model = SaleItem
        fields = ['entered_by',]

enter image description here