There's a simple hack to do this, but it's not a general solution and requires modifying every ModelAdmin
which you want to support this. Maybe there is a general way to do this, but I've not spent the time to solve it on a general level.
The first step is to write a custom FilterSpec
for the filter (see Harley's post for links that will help) which saves the chosen filter value in the session (and deletes it when no longer wanted).
# in cust_admin/filterspecs.py
from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
class MyFilterSpec(ChoicesFilterSpec):
def __init__(self, f, request, params, model, model_admin):
super(MyFilterSpec, self).__init__(f, request, params, model,
model_admin)
if self.lookup_val is not None:
request.session[self.lookup_kwarg] = self.lookup_val
elif self.lookup_kwarg in request.session:
del(request.session[self.lookup_kwarg])
# Register the filter with a test function which will apply it to any field
# with a my_filter attribute equal to True
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'my_filter', False),
MyFilterSpec))
You must import the module this is in somewhere, for example your urls.py
:
# in urls.py
from cust_admin import filterspecs
Set a property on the field you want to apply the filter to:
# in models.py
class MyModel(models.Model):
my_field = Models.IntegerField(choices=MY_CHOICES)
my_field.my_filter = True
In a custom ModelAdmin
class, override the change_view
method, so that after the user clicks save, they are returned to the list view with their filter field value added to the URL.
class MyModelAdmin(admin.ModelAdmin):
def change_view(self, request, object_id, extra_context=None):
result = super(MyModelAdmin, self).change_view(request, object_id,
extra_context)
if '_save' in request.POST:
if 'my_field__exact' in request.session:
result['Location'] = '/admin/myapp/mymodel/?my_field__exact=%s' \
% request.session['my_field__exact']
return result