django: list_filter using a friendly name

  • Last Update :
  • Techknowledgy :

As Aamir says, if you define labels on your fields in your model, you should see the more attractive filter options:

class MyModel(models.Model):
   countryid = models.ForeignKey(Country,
      verbose_name = "Country", null = True,
      db_column = 'countryID', blank = True)

Suggestion : 2

assuming that Country is name of another Model - this should show up in the Admin filter view.,Django How would I filter Friend objects elegantly by name when using the built in User model?,Django Rest Framework - Could not resolve URL for hyperlinked relationship using view name "user-detail",Django - pass a list of results when querying using filter

As Aamir says, if you define labels on your fields in your model, you should see the more attractive filter options:

class MyModel(models.Model):
   countryid = models.ForeignKey(Country,
      verbose_name = "Country", null = True,
      db_column = 'countryID', blank = True)

Suggestion : 3

2. How to associate model with current user while saving?,1. How to show image from Imagefield in Django admin.,3. How to mark a field as readonly in admin?,4. How to create a single Django admin from two different models?

@admin.register(Hero)
class HeroAdmin(admin.ModelAdmin):
   list_display = ("name", "is_immortal", "category", "origin", "is_very_benevolent")
list_filter = ("is_immortal", "category", "origin", )

def is_very_benevolent(self, obj):
   return obj.benevolence_factor > 75
class IsVeryBenevolentFilter(admin.SimpleListFilter):
   title = 'is_very_benevolent'
parameter_name = 'is_very_benevolent'

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

def queryset(self, request, queryset):
   value = self.value()
if value == 'Yes':
   return queryset.filter(benevolence_factor__gt = 75)
elif value == 'No':
   return queryset.exclude(benevolence_factor__gt = 75)
return queryset

Suggestion : 4

Here the is_staff field will use the BooleanFieldListFilter. Specifying only the field name, fields will automatically use the appropriate filter for most cases, but this format allows you to control the filter used.,Using a field name and an explicit FieldListFilter,A 2-tuple containing a field name and a subclass of django.contrib.admin.FieldListFilter.,ModelAdmin List Filters Using a field name Using a SimpleListFilter Using a field name and an explicit FieldListFilter

class PersonAdmin(admin.ModelAdmin):
   list_filter = ('is_staff', 'company')
class PersonAdmin(admin.UserAdmin):
   list_filter = ('company__name', )
from datetime
import date

from django.contrib
import admin
from django.utils.translation
import gettext_lazy as _

class DecadeBornListFilter(admin.SimpleListFilter):
   # Human - readable title which will be displayed in the
# right admin sidebar just above the filter options.
title = _('decade born')

# Parameter
for the filter that will be used in the URL query.
parameter_name = 'decade'

def lookups(self, request, model_admin):
   ""
"
Returns a list of tuples.The first element in each
tuple is the coded value
for the option that will
appear in the URL query.The second element is the
human - readable name
for the option that will appear
   in the right sidebar.
""
"
return (
   ('80s', _('in the eighties')),
   ('90s', _('in the nineties')),
)

def queryset(self, request, queryset):
   ""
"
Returns the filtered queryset based on the value
provided in the query string and retrievable via `self.value()`.
""
"
# Compare the requested value(either '80s'
   or '90s')
# to decide how to filter the queryset.
if self.value() == '80s':
   return queryset.filter(
      birthday__gte = date(1980, 1, 1),
      birthday__lte = date(1989, 12, 31),
   )
if self.value() == '90s':
   return queryset.filter(
      birthday__gte = date(1990, 1, 1),
      birthday__lte = date(1999, 12, 31),
   )

class PersonAdmin(admin.ModelAdmin):
   list_filter = (DecadeBornListFilter, )
class AuthDecadeBornListFilter(DecadeBornListFilter):

   def lookups(self, request, model_admin):
   if request.user.is_superuser:
   return super().lookups(request, model_admin)

def queryset(self, request, queryset):
   if request.user.is_superuser:
   return super().queryset(request, queryset)
class AdvancedDecadeBornListFilter(DecadeBornListFilter):

   def lookups(self, request, model_admin):
   ""
"
Only show the lookups
if there actually is
anyone born in the corresponding decades.
""
"
qs = model_admin.get_queryset(request)
if qs.filter(
      birthday__gte = date(1980, 1, 1),
      birthday__lte = date(1989, 12, 31),
   ).exists():
   yield('80s', _('in the eighties'))
if qs.filter(
      birthday__gte = date(1990, 1, 1),
      birthday__lte = date(1999, 12, 31),
   ).exists():
   yield('90s', _('in the nineties'))
class PersonAdmin(admin.ModelAdmin):
   list_filter = (
      ('is_staff', admin.BooleanFieldListFilter),
   )

Suggestion : 5

Then just use formfield_for_foreignkey() which is described in django document to filter the objects we want. , I might want to make it so that by default only hosts that are not marked as decommissioned are displayed by default in the index. It would be nice if I could just pass an option to list_filter to set the a filter that is enabled by default. Perhaps something like this: , That's a great idea to add this feature. for now, I make a bit hack of code to set django.contrib.admin.filterspecs.RelatedFilterSpec.lookup_choices to get objects from "ModelAdmin.formfield_for_foreignkey()" , There should be a way to set a default list_filter in the admin interface. For example, if I had a model like this:

DECOM_CHOICES = (
   ('N', 'No'),
   ('Y', 'Yes'),
)

class Host(models.Model):
   hostname = models.CharField(max_length = 36, unique = True)
decommissioned = models.CharField(max_length = 1, choices = DECOM_CHOICES,
   default = 'N')
ip_address = models.IPAddressField()
def __unicode__(self):
   return self.hostname

class HostAdmin(admin.ModelAdmin):
   fieldsets = [
      ('Host Info', {
         'fields': ['hostname', 'decommissioned', 'ip_address']
      }),
      list_display = ('hostname', 'ip_address', 'decommissioned')
      list_filter = ('decommissioned')

      admin.site.register(Host, HostAdmin)
list_filter = ('decommissioned__exact=N') # Matches the URL
if you click on "No" in the filter list
list_filter = ('decommissioned__default') # Have it choose the same
default as specified in the model.

That's a great idea to add this feature.
for now, I make a bit hack of code to set django.contrib.admin.filterspecs.RelatedFilterSpec.lookup_choices to get objects from "ModelAdmin.formfield_for_foreignkey()"

class RelatedFilterSpec(FilterSpec):
   def __init__(self, f, request, params, model, model_admin):
   super(RelatedFilterSpec, self).__init__(f, request, params, model, model_admin)
if isinstance(f, models.ManyToManyField):
   self.lookup_title = f.rel.to._meta.verbose_name
else:
   self.lookup_title = f.verbose_name
rel_name = f.rel.get_related_field().name
self.lookup_kwarg = '%s__%s__exact' % (f.name, rel_name)
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
# self.lookup_choices = f.rel.get_choices(include_blank = False); >> f.rel.get_choices will
return lists of object tuple
self.lookup_choices = [];
for object in model_admin.formfield_for_foreignkey(f, request).queryset:
   list = (object.id, object.__str__());
self.lookup_choices.append(list);

Say you have an is_archived flag on a model and you want to default filter the list to hide archived items:

class ArchivedListFilter(admin.SimpleListFilter):

   title = _('Archived')
parameter_name = 'show_archived'

def lookups(self, request, model_admin):
   return (
      ('all', _('Show all')),
      ('archived', _('Show archived only')),
   )

def queryset(self, request, queryset):
   show_archived = request.GET.get('show_archived')
if (show_archived == 'all'):
   return queryset.all()
elif(show_archived == 'archived'):
   return queryset.filter(is_archived = True)
return queryset.filter(is_archived = False)

def choices(self, cl):
   yield {
      'selected': self.value() is None,
      'query_string': cl.get_query_string({}, [self.parameter_name]),
      'display': _('Hide archived'),
      # Changed All to Hide archived.
   }
for lookup, title in self.lookup_choices:
   yield {
      'selected': self.value() == force_text(lookup),
      'query_string': cl.get_query_string({
         self.parameter_name: lookup,
      }, []),
      'display': title,
   }

Here's how I did it with FieldListFilter:

class DeactivableListFilter(admin.ListFilter):

   title = _("active")
parameter_name = 'active'

def __init__(self, request, params, model, model_admin):
   super().__init__(request, params, model, model_admin)
if self.parameter_name in params:
   value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value

def show_all(self):
   return self.used_parameters.get(self.parameter_name) == '__all__'

def has_output(self):
   return True

def choices(self, changelist):
   return [{
         'selected': self.show_all(),
         'query_string': changelist.get_query_string({
            self.parameter_name: '__all__'
         }),
         'display': "Tout",
      },
      {
         'selected': not self.show_all(),
         'query_string': changelist.get_query_string(remove = [self.parameter_name]),
         'display': "Actif",
      },
   ]

def queryset(self, request, queryset):
   if not self.show_all():
   return queryset.filter(active = True)

def expected_parameters(self):
   return [self.parameter_name]

Suggestion : 6

In this article, we'll learn how to Add list_display, list_filter, and search_fields in Django Admin Interface.,Now, we'll add some options to our Django model admin like list_display, list_filter, and search_fields.,So in this article, we have learned how to display multi fields in Django admin interface, we've also learned how to add filtering list and the search field to our Django admin for the models., 3. Adding search_fields to Django Admin

1._
class EcoProduct(models.Model):
   name = models.CharField(max_length = 300)
price = models.DecimalField(max_digits = 6, decimal_places = 2)
category = models.CharField(max_length = 300)
date = models.DateField(auto_now_add = True)

def __str__(self):
   return self.name
2._
python manage.py makemigrations
3._
python manage.py migrate
5._
list_display = ['Field']
6._
admin.site.register(EcoProduct)