How can I change the default filter choice from \'ALL\'? I have a field named as status
which has three values: activate
, pending
and
Note that if instead of pre-selecting a filter value you want to always pre-filter the data before showing it in the admin, you should override the ModelAdmin.queryset()
method instead.
Took ha22109's answer above and modified to allow the selection of "All" by comparing HTTP_REFERER
and PATH_INFO
.
class MyModelAdmin(admin.ModelAdmin):
def changelist_view(self, request, extra_context=None):
test = request.META['HTTP_REFERER'].split(request.META['PATH_INFO'])
if test[-1] and not test[-1].startswith('?'):
if not request.GET.has_key('decommissioned__exact'):
q = request.GET.copy()
q['decommissioned__exact'] = 'N'
request.GET = q
request.META['QUERY_STRING'] = request.GET.urlencode()
return super(MyModelAdmin,self).changelist_view(request, extra_context=extra_context)
You can simply usereturn queryset.filter()
or if self.value() is None
and Override method of SimpleListFilter
from django.utils.encoding import force_text
def choices(self, changelist):
for lookup, title in self.lookup_choices:
yield {
'selected': force_text(self.value()) == force_text(lookup),
'query_string': changelist.get_query_string(
{self.parameter_name: lookup}, []
),
'display': title,
}
class MyModelAdmin(admin.ModelAdmin):
def changelist_view(self, request, extra_context=None):
if not request.GET.has_key('decommissioned__exact'):
q = request.GET.copy()
q['decommissioned__exact'] = 'N'
request.GET = q
request.META['QUERY_STRING'] = request.GET.urlencode()
return super(MyModelAdmin,self).changelist_view(request, extra_context=extra_context)
Here is my generic solution using redirect, it just checks if there are any GET parameters, if none exist then it redirects with the default get parameter. I also have a list_filter set so it picks that up and displays the default.
from django.shortcuts import redirect
class MyModelAdmin(admin.ModelAdmin):
...
list_filter = ('status', )
def changelist_view(self, request, extra_context=None):
referrer = request.META.get('HTTP_REFERER', '')
get_param = "status__exact=5"
if len(request.GET) == 0 and '?' not in referrer:
return redirect("{url}?{get_parms}".format(url=request.path, get_parms=get_param))
return super(MyModelAdmin,self).changelist_view(request, extra_context=extra_context)
The only caveat is when you do a direct get to the page with "?" present in the url, there is no HTTP_REFERER set so it will use the default parameter and redirect. This is fine for me, it works great when you click through the admin filter.
UPDATE:
In order to get around the caveat, I ended up writing a custom filter function which simplified the changelist_view functionality. Here is the filter:
class MyModelStatusFilter(admin.SimpleListFilter):
title = _('Status')
parameter_name = 'status'
def lookups(self, request, model_admin): # Available Values / Status Codes etc..
return (
(8, _('All')),
(0, _('Incomplete')),
(5, _('Pending')),
(6, _('Selected')),
(7, _('Accepted')),
)
def choices(self, cl): # Overwrite this method to prevent the default "All"
from django.utils.encoding import force_text
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,
}
def queryset(self, request, queryset): # Run the queryset based on your lookup values
if self.value() is None:
return queryset.filter(status=5)
elif int(self.value()) == 0:
return queryset.filter(status__lte=4)
elif int(self.value()) == 8:
return queryset.all()
elif int(self.value()) >= 5:
return queryset.filter(status=self.value())
return queryset.filter(status=5)
And the changelist_view now only passes the default parameter if none are present. The idea was to get rid of the generics filters capability to view all by using no get parameters. To view all I assigned the status = 8 for that purpose.:
class MyModelAdmin(admin.ModelAdmin):
...
list_filter = ('status', )
def changelist_view(self, request, extra_context=None):
if len(request.GET) == 0:
get_param = "status=5"
return redirect("{url}?{get_parms}".format(url=request.path, get_parms=get_param))
return super(MyModelAdmin, self).changelist_view(request, extra_context=extra_context)
def changelist_view( self, request, extra_context = None ):
default_filter = False
try:
ref = request.META['HTTP_REFERER']
pinfo = request.META['PATH_INFO']
qstr = ref.split( pinfo )
if len( qstr ) < 2:
default_filter = True
except:
default_filter = True
if default_filter:
q = request.GET.copy()
q['registered__exact'] = '1'
request.GET = q
request.META['QUERY_STRING'] = request.GET.urlencode()
return super( InterestAdmin, self ).changelist_view( request, extra_context = extra_context )