Adding filters to Django Admin Site Change List

In order to add filters you need to add list_filter attribute to the ModelAdmin.

So go to myapp/admin.py and add a list_filter attribute to our ProductAdmin class

class ProductAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug': ('name',)}
    list_display = ('name', 'slug', 'is_active', 'id',)
    filter_horizontal = ('category',)
    search_fields = ('name',)
    list_filter = ('category', 'is_active',) #  new


admin.site.register(Product, ProductAdmin)

Now you can see filters to the right from the change list:

image

Writing custom filters for Django Admin Site

There is a plenty of opportunity how to add custom filters, but there are a few typical cases for that.

Custom Django Admin filter multiple values

Look at our Order model. Imagine you want to see all orders in any active state? This would include "New", "Processing" and "Shipped".

Let's make it.

image

First, I have created 1 order in each status.

Let's see what happens if I just add a list_filter attribute with status:

# myapp/admin.py

class OrderAdmin(admin.ModelAdmin):  
    list_display = ('customer', 'created_dt', 'completed_dt', 'status', 'id',)  
    list_filter = ('status',)  


admin.site.register(Order, OrderAdmin)

image

Such filter doesn't help a manager or store owner who wants to see all active orders at a glance.

Let's make a custom admin filter for order status and add it to list_filter

class OnlyActiveOrdersFilter(admin.SimpleListFilter):
    title = 'Show Only Active Orders'
    parameter_name = 'status'

    def lookups(self, request, model_admin):
        return (
            ('active', 'Active'),
        )

    def queryset(self, request, queryset):
        if self.value() == 'active':
            return queryset.filter(status__in=(ORDER_STATUSES.new, ORDER_STATUSES.processing, ORDER_STATUSES.shipped))
        return queryset


class OrderAdmin(admin.ModelAdmin):
    list_display = ('customer', 'created_dt', 'completed_dt', 'status', 'id',)
    list_filter = ('status', OnlyActiveOrdersFilter,)


admin.site.register(Order, OrderAdmin)

image

As you can see if you select filter by "Active" then there will only be 3 orders in the list in statuses "Shipped", "Processing" and "New".