diff -r 95bbd099704f -r cbc7231501d2 django/contrib/admin/filterspecs.py
--- a/django/contrib/admin/filterspecs.py	Thu Jan 17 13:00:44 2008 -0600
+++ b/django/contrib/admin/filterspecs.py	Fri Jan 18 12:39:47 2008 -0600
@@ -14,20 +14,8 @@
 import datetime
 
 class FilterSpec(object):
-    filter_specs = []
-    def __init__(self, f, request, params, model, model_admin):
-        self.field = f
+    def __init__(self, request, params, model, model_admin):
         self.params = params
-
-    def register(cls, test, factory):
-        cls.filter_specs.append((test, factory))
-    register = classmethod(register)
-
-    def create(cls, f, request, params, model, model_admin):
-        for test, factory in cls.filter_specs:
-            if test(f):
-                return factory(f, request, params, model, model_admin)
-    create = classmethod(create)
 
     def has_output(self):
         return True
@@ -36,7 +24,7 @@
         raise NotImplementedError()
 
     def title(self):
-        return self.field.verbose_name
+        raise NotImplementedError()
 
     def output(self, cl):
         t = []
@@ -51,16 +39,35 @@
             t.append('</ul>\n\n')
         return mark_safe("".join(t))
 
-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
+class FieldFilterSpec(FilterSpec):
+    field_filter_specs = []
+    def __init__(self, request, params, model, model_admin, field):
+        super(FilterSpec, self).__init__(request, params, model, model_admin)
+        self.field = field
+
+    def register(cls, test, factory):
+        cls.field_filter_specs.append((test, factory))
+    register = classmethod(register)
+
+    def create(cls, request, params, model, model_admin, field):
+        for test, factory in cls.field_filter_specs:
+            if test(field):
+                return factory(request, params, model, model_admin, field)
+    create = classmethod(create)
+
+    def title(self):
+        return self.field.verbose_name
+
+class RelatedFilterSpec(FieldFilterSpec):
+    def __init__(self, request, params, model, model_admin, field):
+        super(RelatedFilterSpec, self).__init__(request, params, model, model_admin, field)
+        if isinstance(field, models.ManyToManyField):
+            self.lookup_title = field.rel.to._meta.verbose_name
         else:
-            self.lookup_title = f.verbose_name
-        self.lookup_kwarg = '%s__%s__exact' % (f.name, f.rel.to._meta.pk.name)
+            self.lookup_title = field.verbose_name
+        self.lookup_kwarg = '%s__%s__exact' % (field.name, field.rel.to._meta.pk.name)
         self.lookup_val = request.GET.get(self.lookup_kwarg, None)
-        self.lookup_choices = f.rel.to._default_manager.all()
+        self.lookup_choices = field.rel.to._default_manager.all()
 
     def has_output(self):
         return len(self.lookup_choices) > 1
@@ -77,13 +84,12 @@
             yield {'selected': self.lookup_val == smart_unicode(pk_val),
                    'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}),
                    'display': val}
+FieldFilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)
 
-FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)
-
-class ChoicesFilterSpec(FilterSpec):
-    def __init__(self, f, request, params, model, model_admin):
-        super(ChoicesFilterSpec, self).__init__(f, request, params, model, model_admin)
-        self.lookup_kwarg = '%s__exact' % f.name
+class ChoicesFilterSpec(FieldFilterSpec):
+    def __init__(self, request, params, model, model_admin, field):
+        super(ChoicesFilterSpec, self).__init__(request, params, model, model_admin, field)
+        self.lookup_kwarg = '%s__exact' % field.name
         self.lookup_val = request.GET.get(self.lookup_kwarg, None)
 
     def choices(self, cl):
@@ -94,12 +100,11 @@
             yield {'selected': smart_unicode(k) == self.lookup_val,
                     'query_string': cl.get_query_string({self.lookup_kwarg: k}),
                     'display': v}
+FieldFilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec)
 
-FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec)
-
-class DateFieldFilterSpec(FilterSpec):
-    def __init__(self, f, request, params, model, model_admin):
-        super(DateFieldFilterSpec, self).__init__(f, request, params, model, model_admin)
+class DateFieldFilterSpec(FieldFilterSpec):
+    def __init__(self, request, params, model, model_admin, field):
+        super(DateFieldFilterSpec, self).__init__(request, params, model, model_admin, field)
 
         self.field_generic = '%s__' % self.field.name
 
@@ -115,9 +120,9 @@
                        '%s__month' % self.field.name: str(today.month),
                        '%s__day' % self.field.name: str(today.day)}),
             (_('Past 7 days'), {'%s__gte' % self.field.name: one_week_ago.strftime('%Y-%m-%d'),
-                             '%s__lte' % f.name: today_str}),
+                             '%s__lte' % field.name: today_str}),
             (_('This month'), {'%s__year' % self.field.name: str(today.year),
-                             '%s__month' % f.name: str(today.month)}),
+                             '%s__month' % field.name: str(today.month)}),
             (_('This year'), {'%s__year' % self.field.name: str(today.year)})
         )
 
@@ -129,14 +134,13 @@
             yield {'selected': self.date_params == param_dict,
                    'query_string': cl.get_query_string(param_dict, [self.field_generic]),
                    'display': title}
+FieldFilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)
 
-FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)
-
-class BooleanFieldFilterSpec(FilterSpec):
-    def __init__(self, f, request, params, model, model_admin):
-        super(BooleanFieldFilterSpec, self).__init__(f, request, params, model, model_admin)
-        self.lookup_kwarg = '%s__exact' % f.name
-        self.lookup_kwarg2 = '%s__isnull' % f.name
+class BooleanFieldFilterSpec(FieldFilterSpec):
+    def __init__(self, request, params, model, model_admin, field):
+        super(BooleanFieldFilterSpec, self).__init__(request, params, model, model_admin, field)
+        self.lookup_kwarg = '%s__exact' % field.name
+        self.lookup_kwarg2 = '%s__isnull' % field.name
         self.lookup_val = request.GET.get(self.lookup_kwarg, None)
         self.lookup_val2 = request.GET.get(self.lookup_kwarg2, None)
 
@@ -152,17 +156,16 @@
             yield {'selected': self.lookup_val2 == 'True',
                    'query_string': cl.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]),
                    'display': _('Unknown')}
-
-FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec)
+FieldFilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec)
 
 # This should be registered last, because it's a last resort. For example,
 # if a field is eligible to use the BooleanFieldFilterSpec, that'd be much
 # more appropriate, and the AllValuesFilterSpec won't get used for it.
-class AllValuesFilterSpec(FilterSpec):
-    def __init__(self, f, request, params, model, model_admin):
-        super(AllValuesFilterSpec, self).__init__(f, request, params, model, model_admin)
-        self.lookup_val = request.GET.get(f.name, None)
-        self.lookup_choices = model_admin.queryset(request).distinct().order_by(f.name).values(f.name)
+class AllValuesFilterSpec(FieldFilterSpec):
+    def __init__(self, request, params, model, model_admin, field):
+        super(AllValuesFilterSpec, self).__init__(request, params, model, model_admin, field)
+        self.lookup_val = request.GET.get(field.name, None)
+        self.lookup_choices = model_admin.queryset(request).distinct().order_by(field.name).values(field.name)
 
     def title(self):
         return self.field.verbose_name
@@ -176,4 +179,5 @@
             yield {'selected': self.lookup_val == val,
                    'query_string': cl.get_query_string({self.field.name: val}),
                    'display': val}
-FilterSpec.register(lambda f: True, AllValuesFilterSpec)
+FieldFilterSpec.register(lambda f: True, AllValuesFilterSpec)
+
diff -r 95bbd099704f -r cbc7231501d2 django/contrib/admin/views/main.py
--- a/django/contrib/admin/views/main.py	Thu Jan 17 13:00:44 2008 -0600
+++ b/django/contrib/admin/views/main.py	Fri Jan 18 12:39:47 2008 -0600
@@ -1,5 +1,5 @@
 from django import template
-from django.contrib.admin.filterspecs import FilterSpec
+from django.contrib.admin.filterspecs import FieldFilterSpec
 from django.contrib.admin.options import IncorrectLookupParameters
 from django.contrib.admin.views.decorators import staff_member_required
 from django.core.exceptions import ObjectDoesNotExist
@@ -158,9 +158,21 @@
     def get_filters(self, request):
         filter_specs = []
         if self.list_filter and not self.opts.one_to_one_field:
-            filter_fields = [self.lookup_opts.get_field(field_name) for field_name in self.list_filter]
-            for f in filter_fields:
-                spec = FilterSpec.create(f, request, self.params, self.model, self.model_admin)
+            for item in self.list_filter:
+                if callable(item):
+                    spec = item(
+                        request, self.params, self.model, self.model_admin
+                    )
+                else:
+                    if type(item) is tuple:
+                        (name, factory) = item
+                    else:
+                        name = item
+                        factory = FieldFilterSpec.create
+                    f = self.lookup_opts.get_field(name)
+                    spec = factory(
+                        request, self.params, self.model, self.model_admin, f
+                    )
                 if spec and spec.has_output():
                     filter_specs.append(spec)
         return filter_specs, bool(filter_specs)
