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)
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)
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
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),
)
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]
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
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
python manage.py makemigrations
python manage.py migrate
list_display = ['Field']
admin.site.register(EcoProduct)