Django-filter: datetime filter don't support datetime input formats from project settings file

Created on 1 Apr 2017  ·  10Comments  ·  Source: carltongibson/django-filter

I am facing 2 issues:

  1. when using django filter with django rest framework (DRF) datetime filters don't accept iso-8601 formats. DRF renders datetime objects as iso-8061. This creates confusion.

  2. I added iso-8061 to django's datetime input formats setting. But django-filter still did not support it.

All 10 comments

Hi @KushGoyal - which filterset class are you using? django_filters.FilterSet or django_filters.rest_framework.FilterSet?

@rpkilby I am using django_filters.rest_framework.FilterSet

@KushGoyal - That's odd - it's the only obvious answer that comes to mind.

If you look at this line here, you'll see that the DRF filterset specifically uses the IsoDateTimeFilter for datetimes, which should handle your case. This test should verify the behavior.

Could you provide a more complete example of your filterset? An example test case would be even more helpful.

DRF has its own datetime input setting
Django has it own datetime input setting

Are any of these settings used by django_filters?

I am using a DateTimeFromToRangeFilter which does not use IsoDateTimeField. Is there a way I can make DateTimeFromToRangeFilter use iso-8061.

The DateTimeFromToRangeFilter is ultimately just a collection of two forms.DateTimeField fields, which does obey the DATETIME_INPUT_FORMATS setting. That said, DATETIME_INPUT_FORMATS doesn't recognize the 'iso-8601' string. That behavior is specific to DRF.

An alternative is to mix IsoDateTimeFilter with BaseRangeFilter.

An alternative is to mix IsoDateTimeFilter with BaseRangeFilter.

I don't want to be adding a whole DateX... hierarchy mirroring Django here. Either we need to find workarounds (like this suggested) in user land code or we need to push back on Django to handle ISO-8061 in core. (IMO: Django should probably do that by this point — but this isn't something I have bandwidth to advocate for – so if you want it, make noise, write code.)

@rpkilby @carltongibson Would you have an example of mixing IsoDateTimeFilter with BaseRangeFilter?

I am also trying to make DateTimeFromToRangeFilter support ISO 8601, to no avail.

Here is my code so far:

from django.db import models
from django_filters import rest_framework as filters
from .models import Event

class EventFilter (filters.FilterSet):

    date__range = filters.DateTimeFromToRangeFilter(name='date')

    class Meta:

        model = Event

        fields = {
            'date': ['exact', 'lte', 'gte']
        }

        filter_overrides = {
            models.DateTimeField: {
                'filter_class': filters.IsoDateTimeFilter
            },
        }

Thanks!

Hi @lucas-bremond, the CSV filter bases are used as mixins.

class IsoDateTimeRangeFilter(BaseRangeFilter, IsoDateTimeFilter):
    pass


class EventFilter (filters.FilterSet):
    date__range = IsoDateTimeRangeFilter(name='date')

@rpkilby That is indeed working quite perfectly! Thank you!

Just a quick question (the cherry on the cake): is there any easy way to have this new IsoDateTimeRangeFilter filter provide a form identical to DateFromToRangeFilter?

IsoDateTimeRangeFilter:

image

DateFromToRangeFilter:

image

In any case, thank you so much for your help.

That would require custom html/js. The CSV range filter uses a single input and expects two values separated by a comma. The original DateFromToRangeFilter expects two values across two separate inputs, named <name>_0 & <name>_1 (in 2.0, the suffixes change to after & before).

If you want to use two inputs, but submit as a single CSV, then you'd need to write custom form html that presents the two inputs, then JS that intercepts the form submit, combines them as a single input, then submits the altered data.

Was this page helpful?
0 / 5 - 0 ratings