silentsokolov / django-admin-rangefilter

A Django app that lets you filter data by date range and numeric range in the admin UI
MIT License
721 stars 106 forks source link

Add custom predefined date ranges #51

Closed vekerdyb closed 1 year ago

vekerdyb commented 4 years ago

Is it possible to add quick-selections such as "This month", "Last month", "Next month", "This week", ...?

wlisesrivas commented 4 years ago

Is it possible to add quick-selections such as "This month", "Last month", "Next month", "This week", ...?

Django admin default date filter has similar behavior image

robertpro commented 2 years ago

I would like to mix both, date range + no date + has date, any suggestion @wlisesrivas ?

robertpro commented 2 years ago

@vekerdyb This is the code I will use:

class DateRangeListFilter(admin.DateFieldListFilter, DateRangeFilter):
    template = 'admin/filters/date_filter.html'

    def expected_parameters(self):
        params = [self.lookup_kwarg_gte, self.lookup_kwarg_lte]
        if self.field.null:
            params.append(self.lookup_kwarg_isnull)
        return params

    def _make_query_filter(self, request, validated_data):
        query_params = super()._make_query_filter(request, validated_data)
        date_value_gte = validated_data.get(self.lookup_kwarg_gte, None)
        date_value_lte = validated_data.get(self.lookup_kwarg_lte, None)
        date_value_isnull = validated_data.get(self.lookup_kwarg_isnull, None)

        if date_value_isnull is not None and not any([date_value_lte, date_value_gte]):
            query_params[self.lookup_kwarg_isnull] = date_value_isnull

        return query_params

    def _get_form_fields(self):
        fields = super()._get_form_fields()
        fields.update(OrderedDict(
            (
                (self.lookup_kwarg_isnull, forms.BooleanField(
                    label='',
                    localize=True,
                    required=False,
                    widget=forms.HiddenInput,
                )),
            )
        ))
        return fields

Same as rangefilter/date_filter.html, but inserting Django admin/filter.html here, which is this code in my case.

...
<ul>
    {% for choice in choices %}
        <li{% if choice.selected %} class="selected"{% endif %}>
            <a href="{{ choice.query_string|iriencode }}" title="{{ choice.display }}">{{ choice.display }}</a>
        </li>
    {% endfor %}
</ul>
...

Result: image

jerinpetergeorge commented 2 years ago

Any plans to include this in the package? @silentsokolov

Nagendra-babu77 commented 1 year ago

@vekerdyb This is the code I will use:

class DateRangeListFilter(admin.DateFieldListFilter, DateRangeFilter):
    template = 'admin/filters/date_filter.html'

    def expected_parameters(self):
        params = [self.lookup_kwarg_gte, self.lookup_kwarg_lte]
        if self.field.null:
            params.append(self.lookup_kwarg_isnull)
        return params

    def _make_query_filter(self, request, validated_data):
        query_params = super()._make_query_filter(request, validated_data)
        date_value_gte = validated_data.get(self.lookup_kwarg_gte, None)
        date_value_lte = validated_data.get(self.lookup_kwarg_lte, None)
        date_value_isnull = validated_data.get(self.lookup_kwarg_isnull, None)

        if date_value_isnull is not None and not any([date_value_lte, date_value_gte]):
            query_params[self.lookup_kwarg_isnull] = date_value_isnull

        return query_params

    def _get_form_fields(self):
        fields = super()._get_form_fields()
        fields.update(OrderedDict(
            (
                (self.lookup_kwarg_isnull, forms.BooleanField(
                    label='',
                    localize=True,
                    required=False,
                    widget=forms.HiddenInput,
                )),
            )
        ))
        return fields

Same as rangefilter/date_filter.html, but inserting Django admin/filter.html here, which is this code in my case.

...
<ul>
    {% for choice in choices %}
        <li{% if choice.selected %} class="selected"{% endif %}>
            <a href="{{ choice.query_string|iriencode }}" title="{{ choice.display }}">{{ choice.display }}</a>
        </li>
    {% endfor %}
</ul>
...

Result: image

Not working for me.. got object has no attribute self.lookup_kwarg_isnull

robertpro commented 1 year ago

@Nagendra-babu77 , there is a bug on my snippet, use this one:

class DateRangeListFilter(admin.DateFieldListFilter, DateRangeFilter):
    template = 'admin/filters/date_range_filter.html'

    def expected_parameters(self):
        params = [self.lookup_kwarg_gte, self.lookup_kwarg_lte]
        if self.field.null:
            params.append(self.lookup_kwarg_isnull)
        return params

    def _make_query_filter(self, request, validated_data):
        query_params = super()._make_query_filter(request, validated_data)
        date_value_gte = validated_data.get(self.lookup_kwarg_gte, None)
        date_value_lte = validated_data.get(self.lookup_kwarg_lte, None)
        date_value_isnull = validated_data.get(self.lookup_kwarg_isnull, None)

        if date_value_isnull is not None and not any([date_value_lte, date_value_gte]):
            query_params[self.lookup_kwarg_isnull] = date_value_isnull

        return query_params

    def _get_form_fields(self):
        fields = super()._get_form_fields()
        if self.field.null:
            fields.update(OrderedDict(
                (
                    (self.lookup_kwarg_isnull, forms.BooleanField(
                        label='',
                        localize=True,
                        required=False,
                        widget=forms.HiddenInput,
                    )),
                )
            ))
        return fields

@silentsokolov I have used this code for more than a year, please let me know if it looks good to add it in a PR

silentsokolov commented 1 year ago

Looks good. If you want create PR, please add a new class like DateRangeQuickSelectListFilter Thx!