Skip to content

admin

Walks django.contrib.admin.site._registry and validates that every entry in each ModelAdmin actually resolves to a field, method, or callable on the model or the admin class itself.

What it checks

  • list_display — each entry must be a method, callable, or model field.
  • list_filter — each non-callable entry must be a real model field.
  • search_fields — each entry must be a real model field (lookups like client__raison_sociale are split on __ and the first segment validated).
  • ordering — each entry must be a real model field (optionally prefixed by - for descending).

Example

class SilentWidgetAdmin(admin.ModelAdmin):
    list_display  = ("name", "fnction")      # typo
    search_fields = ("nmae",)                # typo
    ordering      = ("nonexistent",)         # wrong field name
[ERROR:admin.list_display.missing_field]   tests.sample_app.admin.SilentWidgetAdmin
  list_display entry 'fnction' is not a field or callable on SilentWidget
  or SilentWidgetAdmin.
[ERROR:admin.search_fields.missing_field]  tests.sample_app.admin.SilentWidgetAdmin
[ERROR:admin.ordering.missing_field]       tests.sample_app.admin.SilentWidgetAdmin

Why Django won't tell you

The admin only evaluates these tuples lazily — when someone opens the change list page in a browser. Unit tests that never open that page pass happily. Doctor runs the same lookups at check time.

Tuning

[tool.django-doctor.admin]
skip_apps = ["admin", "auth", "contenttypes", "sessions"]

Contrib apps are skipped by default (their admin is Django's).