Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default Boolean Filter in Django Admin

I have seen the solution for a default choice field. Default filter in Django admin

It's not obvious how to extend that to a boolean field. I have an archive field that keeps things from being displayed. I'd like the default filter to be No instead of All.

like image 306
RandO Avatar asked Jul 31 '26 22:07

RandO


2 Answers

class BooleanDefaultNoFilter(SimpleListFilter):
    def lookups(self, request, model_admin):
        return (
            ('all', 'All'),
            (1, 'Yes'),
            (None, 'No')
        )

    def choices(self, changelist):
        for lookup, title in self.lookup_choices:
            yield {
                'selected': self.value() == (str(lookup) if lookup else lookup),
                'query_string': changelist.get_query_string({self.parameter_name: lookup}, []),
                'display': title,
            }

    def queryset(self, request, queryset):
        if self.value():
            if self.value() == 'all':
                return queryset
            else:
                return queryset.filter(**{self.parameter_name: self.value()})

        elif self.value() == None:
            return queryset.filter(**{self.parameter_name: False})

class NamedFilter(BooleanDefaultNoFilter):
    title = _('InsertName')
    parameter_name = 'insertname'

class InsertNameAdmin(admin.ModelAdmin):
      list_filters = (NamedFilter)
like image 92
Andrew Cassidy Avatar answered Aug 03 '26 23:08

Andrew Cassidy


I wanted the filter to show only Yes/No (without All), and to have Yes by default. That way I can avoid some of the confusion for the user to see the All option selected while actually having the Yes filter applied.

I came up with this:

class DefaultYesBooleanFieldListFilter(BooleanFieldListFilter):
    default = "1"

    def __init__(self, field, request, params, model, model_admin, field_path):
        super().__init__(field, request, params, model, model_admin, field_path)
        if not self.lookup_val:
            self.lookup_val = self.default
            self.used_parameters[self.lookup_kwarg] = self.default

    def choices(self, changelist):
        choices = super().choices(changelist)
        choices.__next__()
        for choice in choices:
            print(choice)
            yield choice


class DefaultNoBooleanFieldListFilter(DefaultYesBooleanFieldListFilter):
    default = "0"

Usage: the same as a normal BooleanFieldListFilter, that is,

class SomethingAdmin(admin.ModelAdmin):
    list_filter = (
        ("active", DefaultYesBooleanFieldListFilter),
    )

Note that users will still have the general link to show all results (or remove all filters) which will still cause some confusion.

I hope it's helpful for someone.

like image 40
Pere Picornell Avatar answered Aug 03 '26 23:08

Pere Picornell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!