Django add additional range filter

Copy change_list.html template from here

https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_list.html to your templates (name it for example custom_change_list.html).

Add next to block result_list

{% block result_list %}
        <div style="float: right">{{ range_form }} <button type="button" class="button" onclick="apply_range()">Apply</button></div>

...

Also you can append <script> section to {% block content %} that will put dates into date GET param:

<script>
      function apply_range() {
        var fy = document.getElementById('id_from_date_year').value;
        var fm = document.getElementById('id_from_date_month').value;
        var fd = document.getElementById('id_from_date_day').value;
        var ty = document.getElementById('id_to_date_year').value;
        var tm = document.getElementById('id_to_date_month').value;
        var td = document.getElementById('id_to_date_day').value;
        window.location.href = '/admin/someurl/?date__gte='+fy+'-'+fm+'-'+fd+'&date__lt=+ty+'-'+tm+'-'+td+';
      }
</script>

This param will be mapped into iternal queryset for your model, so models will be filtered by field named date.

Add next to admin.py:

class RangeForm(forms.Form):
    yrs = [(datetime.datetime.now().year - i) for i in range(6)]

    from_date = forms.DateField(widget=SelectDateWidget(years=yrs))
    to_date = forms.DateField(widget=SelectDateWidget(years=yrs))

class Ma(admin.ModelAdmin):
    change_list_template = 'custom_change_list.html'

    def changelist_view(self, request, extra_context=None):
        extra_context = extra_context or {}

        if 'date__gte' in request.GET:
            from_date = request.GET['date__gte'].split('t')
            to_date = request.GET['date__lt'].split('t')
            initial = {
                'from_date':  datetime.datetime.strptime(from_date, '%Y-%m-%d').date(),
                'to_date': datetime.datetime.strptime(to_date, '%Y-%m-%d').date()
            }
        else:
            initial = {
                'from_date': (datetime.datetime.now() - timedelta(days=365*5)).date(),
                'to_date': datetime.datetime.now().date()}
        extra_context['range_form'] = RangeForm(initial=initial)
        return super(Ma, self).changelist_view(request, extra_context=extra_context)

Using non-model fields

If your model has no date field and you want to use it for some other case (aggregations, etc) then you should add date get param to admin.views.main.IGNORED_PARAMS.

In admin.py add:

from django.contrib.admin.views import main as views_main
views_main.IGNORED_PARAMS += ('date',)  
#django
menu 0
Ivan Borshchov profile picture
May 05, 2017
by Ivan Borshchov
Did it help you?
Yes !
No

Best related

Other by Ivan Borshchov