pythondjangorangedjango-admindjango-admin-filters

Django admin: Filter field by range


I have a model called Person. Person has fields like name/surname and age. Now what I want to achieve is to have a filter in django admin that can filter age in some custom ranges so 10-15.

After reading some posts my best shoot is:

class RangeFilter(SimpleListFilter):
    title = 'Age filter'
    parameter_name = 'age'
    
    def lookups(self, request, model_admin):
        
        return [
            (1, '0-5'),
            (2, '5-10'),
            (3, '10-15'),
            (4, '15-20')]

    def queryset(self, request, queryset):
        filt_age = request.GET.get('age')
        return queryset.filter(
                    age__range=self.age_dict[filt_age]
                )

But this yields an error 'RangeFilter' object has no attribute 'age_dict'.


Solution

  • I don't know what you are trying to do but I give you the example below to filter persons by age following the documentation:

    # "store/models.py"
    
    from django.db import models
    
    class Person(models.Model):
        name = models.CharField(max_length=20)
        age =  models.IntegerField()
    
        def __str__(self):
            return self.name
    
    # "store/admin.py"
    
    from django.contrib import admin
    from .models import Person
    
    class PersonAgeFilter(admin.SimpleListFilter):
        title = 'Person Age Filter'
        parameter_name = 'age'
    
        def lookups(self, request, model_admin):
            return (
                ("0-19", '0-19 years'),
                ("20-39", '20-39 years'),
                ("40-59", '40-59 years'),
                ("60<=", '60 years and over'),
            )
    
        def queryset(self, request, queryset):
            if self.value() == '0-19':
                return queryset.filter(age__lte=19)
            if self.value() == '20-39':
                return queryset.filter(age__range=(20, 39))
            if self.value() == '40-59':
                return queryset.filter(age__range=(40, 59))
            if self.value() == '60<=':
                return queryset.filter(age__gte=60)
    
    @admin.register(Person)
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('name', 'age')
        list_filter = (PersonAgeFilter,)
    

    Then, the filter section appears and there are 6 persons as shown below:

    enter image description here

    Then, when clicking on 20-39 year, 6 persons are filtered to 3 persons as shown below:

    enter image description here