I have a DateTimeField named 'session_start' in a model. I am trying to filter the session_start field within a date range.
Model.py
class TimeCard(models.Model):
    profile = models.ForeignKey(settings.AUTH_USER_MODEL)
    session_start = models.DateTimeField()
Filter need to follow the following conditions:
start_date = 30 days back from today.
end_date = today.
I wrote the following code for filtering the "session_start" field within the range between "start_date" and "end_date". Now I am stuck at checking condition where start_date is greater than end_date. What can I do to make the validation?
filter.py
class TimeCardFilter(filters.FilterSet):
    start_date = django_filters.DateTimeFilter(name="session_start", lookup_type='gte')
    end_date = django_filters.DateTimeFilter(name="session_start", lookup_type='lte')
    class Meta:
        model = TimeCard
        fields = ['profile', 'start_date', 'end_date']
                You can actually use django forms in django-filters Filtersets, so you can manage the validation in the form's clean() method. Your filter.py could look something like this:
import django_filters
from app.models import TimeCard
from django import forms
class TimeCardFilter(django_filters.FilterSet):
    start_date = django_filters.DateTimeFilter(
        name="session_start",
        lookup_type="gte")
    end_date = django_filters.DateTimeFilter(
        name="session_start",
        lookup_type="lte")
    class Meta:
        model = TimeCard
        form = TimeCardForm
class TimeCardForm(forms.Form):
    def clean(self):
        cleaned_data = super(TimeCardForm, self).clean()
        start_date = cleaned_data.get("start_date")
        end_date = cleaned_data.get("end_date")
        if start_date > end_date:
            self._errors['start_date'] = self._errors.get('start_date', [])
            self._errors['start_date'].append("Start date must be before end date.")
        return cleaned_data
                        Based on the source code, you may have limited options. It looks like your best bet is to override the qs property.
class TimeCardFilter(filters.FilterSet):
    start_date = django_filters.DateTimeFilter(name="session_start", lookup_type='gte')
    end_date = django_filters.DateTimeFilter(name="session_start", lookup_type='lte')
    @property
    def qs(self):
        # Parent class defines a property _qs which represents the updated queryset
        if hasattr(self, '_qs'):
           return self._qs
        # qs property is the place that FilterSet generates a query string.
        # it finds the values in the self.form.cleaned_data or self.form[name].value()
        orig_start = self.form.cleaned_data['session_start']
        orig_end = self.form.cleaned_data['session_end']
        # Your conditional logic would go here.
        if orig_start > orig_end:
           # You'll need real values here, these clearly are fake.
           self.form.cleaned_data['session_start'] = now()-30 * 24 * 3600
           self.form.cleaned_data['session_end'] = now()
        # Be sure to return FilterSet's actual QS.
        return super(TimeCardFilter, self).qs()
    class Meta:
        model = TimeCard
        fields = ['profile', 'start_date', 'end_date']
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With