I am facing 2 issues:
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.
I added iso-8061 to django's datetime input formats setting. But django-filter still did not support it.
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.
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
:
DateFromToRangeFilter
:
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.