Search code examples
pythondjangofilteringadmin

Custom Filtering Based on Published Posts (In Django admin)


I'm working on a training project for a social network where users can post their recipes. I want to add the ability to filter users in Django admin based on whether they have published recipes or not. My filter class is:

class UserHasRecipeFilter(admin.SimpleListFilter):
    title = _('Posted recipes')
    parameter_name = 'posted_recipes'

    def lookups(self, request, model_admin):
        return (
            ('yes', _('Yes')),
            ('no', _('No')),
        )

    def queryset(self, request, queryset):
        if self.value() == 'yes':
            return queryset.annotate(recipes_count=Count('recipes')).filter(recipes_count__gt=0)
        elif self.value() == 'no':
            return queryset.annotate(recipes_count=Count('recipes')).filter(recipes_count=0)

Custom filter is added:

@admin.register(UserProfile)
class UserAdmin(UserAdmin):
    list_filter = ('is_active', 'UserHasRecipeFilter’,)

But when I try to run make migrations, It is failing with an following error : ERRORS: <class 'recipes.admin.UserAdmin'>: (admin.E116) The value of 'list_filter[2]' refers to 'UserHasRecipeFilter', which does not refer to a Field.

Please advise where I made a mistake..


Solution

  • The error arises from how you're adding the filter to the list_filter. In Django admin, custom filters are added by specifying the class itself, not a string representation.

    This line:

    list_filter = ('is_active', 'UserHasRecipeFilter',)
    

    Should be replaced with this:

    list_filter = ('is_active', UserHasRecipeFilter,)
    

    With this change your UserAdmin class should look like this:

    @admin.register(UserProfile)
    class UserAdmin(UserAdmin):
        list_filter = ('is_active', UserHasRecipeFilter,)
    

    This will fix your issue.