{"record":{"id":"bbad780eeb0f8e05","repo":"django/django","slug":"the-list-filter-does-not-specify-a-title","errorCode":null,"errorMessage":"The list filter '%' does not specify a 'title'.","messagePattern":"The list filter '%' does not specify a 'title'\\.","errorType":"exception","errorClass":"ImproperlyConfigured","httpStatus":null,"severity":"error","filePath":"django/contrib/admin/filters.py","lineNumber":36,"sourceCode":"    reverse_field_path,\n)\nfrom django.core.exceptions import ImproperlyConfigured, ValidationError\nfrom django.db import models\nfrom django.utils import timezone\nfrom django.utils.translation import gettext_lazy as _\n\n\nclass ListFilter:\n    title = None  # Human-readable title to appear in the right sidebar.\n    template = \"admin/filter.html\"\n\n    def __init__(self, request, params, model, model_admin):\n        self.request = request\n        # This dictionary will eventually contain the request's query string\n        # parameters actually used by this filter.\n        self.used_parameters = {}\n        if self.title is None:\n            raise ImproperlyConfigured(\n                \"The list filter '%s' does not specify a 'title'.\"\n                % self.__class__.__name__\n            )\n\n    def has_output(self):\n        \"\"\"\n        Return True if some choices would be output for this filter.\n        \"\"\"\n        raise NotImplementedError(\n            \"subclasses of ListFilter must provide a has_output() method\"\n        )\n\n    def choices(self, changelist):\n        \"\"\"\n        Return choices ready to be output in the template.\n\n        `changelist` is the ChangeList to be displayed.\n        \"\"\"","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/django/django/blob/ae25a40be07e8a749edf526df37c93e59d4a22c9/django/contrib/admin/filters.py#L18-L54","documentation":"Every ListFilter (and its subclasses) must expose a human-readable title attribute shown in the admin sidebar. ListFilter.__init__ checks self.title and raises ImproperlyConfigured if it is None, because the template would otherwise render an empty filter header. FieldListFilter auto-derives title from the field's verbose_name, but custom filters that subclass ListFilter or SimpleListFilter directly must set title themselves.","triggerScenarios":"Raised in ListFilter.__init__ (filters.py:35-39) when instantiating a filter whose class sets title = None (the default) and does not override it. Fires when Django builds the changelist filter sidebar for a ModelAdmin whose list_filter references such a filter class.","commonSituations":"Writing a custom SimpleListFilter and forgetting to set title. Copying a filter skeleton that omitted title. Subclassing ListFilter directly (rather than SimpleListFilter) and missing required attributes.","solutions":["Add a title class attribute: class MyFilter(admin.SimpleListFilter): title = 'My Filter'.","For SimpleListFilter, also set parameter_name (a separate check) — both are required.","If using FieldListFilter, title is auto-derived so this only triggers for fully custom filters."],"exampleFix":"// before\nclass PublishedFilter(admin.SimpleListFilter):\n    parameter_name = 'published'\n    # missing title\n    def lookups(self, request, model_admin): return [('yes', 'Yes')]\n    def queryset(self, request, qs): return qs\n\n// after\nclass PublishedFilter(admin.SimpleListFilter):\n    title = 'Published'\n    parameter_name = 'published'\n    def lookups(self, request, model_admin): return [('yes', 'Yes')]\n    def queryset(self, request, qs): return qs","handlingStrategy":"validation","validationCode":"def validate_list_filter(filter_cls):\n    if getattr(filter_cls, \"title\", None) is None:\n        raise TypeError(f\"{filter_cls.__name__} must define a non-None 'title' attribute.\")\n    return filter_cls","typeGuard":"def has_title(filter_cls) -> bool:\n    return getattr(filter_cls, \"title\", None) is not None","tryCatchPattern":null,"preventionTips":["Always set title (and parameter_name for SimpleListFilter) on custom filters.","Prefer SimpleListFilter / FieldListFilter over bare ListFilter.","Add a unit test that instantiates each filter with a dummy request."],"tags":["django-admin","filters","improperly-configured","configuration"],"analyzedSha":"ae25a40be07e8a749edf526df37c93e59d4a22c9","analyzedAt":"2026-08-06T21:46:51.801Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}