# Extension points — django/django

> Canonical page: https://codevetter.com/unpack/django/extension-points

# Extension points — django/django

Scanned commit dd6f6b1531984823e3dc56740dfa93f3ceb09357 (2026-09-20). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Django is built as registries plus import strings. New behavior is expected to plug in through INSTALLED_APPS, MIDDLEWARE, management command modules, database and cache and task backends, URL converters, lookups, template libraries, checks, signals, admin classes, and serializers. Most of these are configured from settings rather than a single plugin entry file. Contrib apps are ordinary apps that happen to ship in the django package.
- Application plugins are INSTALLED_APPS entries. AppConfig.create loads each entry; ready() runs after models import. Duplicate labels or duplicate app names raise ImproperlyConfigured. startapp scaffolds from django/conf/app_template/*.py-tpl. — [django/apps/registry.py#L86-124](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/apps/registry.py#L86-L124) [django/__init__.py#L8-25](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/__init__.py#L8-L25)
- HTTP plugins are dotted paths in settings.MIDDLEWARE. BaseHandler.load_middleware import_string's each one and requires sync_capable or async_capable. MiddlewareNotUsed drops an entry at runtime. — [django/core/handlers/base.py#L27-70](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/core/handlers/base.py#L27-L70) [django/conf/global_settings.py#L475-482](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/conf/global_settings.py#L475-L482)
- CLI plugins are modules named management/commands/<name>.py inside an installed app (or django.core). find_commands lists them; load_command_class imports module.Command. Later apps override earlier command names. — [django/core/management/__init__.py#L29-80](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/core/management/__init__.py#L29-L80)
- Auth plugins are AUTHENTICATION_BACKENDS (default ModelBackend) and PASSWORD_HASHERS. get_hasher('default') returns the first hasher. A custom hasher subclasses BasePasswordHasher and must set algorithm, verify, encode, and safe_summary. — [django/conf/global_settings.py#L534-556](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/conf/global_settings.py#L534-L556) [django/contrib/auth/hashers.py#L121-169](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/contrib/auth/hashers.py#L121-L169) [django/contrib/auth/hashers.py#L209-216](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/contrib/auth/hashers.py#L209-L216) [django/contrib/auth/__init__.py#L123-139](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/contrib/auth/__init__.py#L123-L139)
- Database plugins are DATABASES[alias]['ENGINE'] pointing at a backend package with DatabaseWrapper, plus optional DATABASE_ROUTERS. The dummy backend is the empty-ENGINE fallback. Custom lookups register via RegisterLookupMixin.register_lookup, which writes class_lookups or instance_lookups. — [django/db/backends/sqlite3/base.py#L60](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/db/backends/sqlite3/base.py#L60) [django/db/backends/dummy/base.py#L1-25](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/db/backends/dummy/base.py#L1-L25) [django/conf/global_settings.py#L184-189](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/conf/global_settings.py#L184-L189) [django/db/models/query_utils.py#L379-404](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/db/models/query_utils.py#L379-L404)
- URL plugins: path, re_path, and include build URLPattern and URLResolver trees. register_converter adds path converters; built-ins include IntConverter, StringConverter, UUIDConverter, SlugConverter, and PathConverter. — [django/urls/__init__.py#L1-53](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/urls/__init__.py#L1-L53) [django/urls/converters.py#L5-40](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/urls/converters.py#L5-L40) [django/urls/resolvers.py#L505-523](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/urls/resolvers.py#L505-L523)
- Template plugins: a templatetags module exposes a Library (conventionally register). Engine accepts libraries and extra builtins. default_builtins are defaulttags, defaultfilters, and loader_tags. — [django/template/library.py#L17-55](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/template/library.py#L17-L55) [django/template/engine.py#L13-60](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/template/engine.py#L13-L60)
- System checks plug in through CheckRegistry.register, usable as a decorator with tags. deploy=True puts the check in deployment_checks, which run_checks includes only when asked. Tags include admin, models, security, database, and urls. — [django/core/checks/registry.py#L8-99](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/core/checks/registry.py#L8-L99)
- Signals: django.dispatch.Signal is the shared bus. ORM code sends pre_save and post_save. Request lifecycle uses request_started and request_finished. Task backends send task_enqueued, task_started, and task_finished. Receivers can be sync or async. — [django/dispatch/dispatcher.py#L68-80](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/dispatch/dispatcher.py#L68-L80) [django/db/models/base.py#L981-1024](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/db/models/base.py#L981-L1024) [django/tasks/backends/immediate.py#L29-72](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/tasks/backends/immediate.py#L29-L72) [django/db/__init__.py#L46-63](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/db/__init__.py#L46-L63)
- Admin plugins: subclass ModelAdmin and call AdminSite.register(model, admin_class) or admin.site.register. Keyword options to register() build a dynamic subclass. Autodiscover imports each app's admin module. — [django/contrib/admin/sites.py#L95-149](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/contrib/admin/sites.py#L95-L149)
- Cache, task, and mailer backends are alias maps of BACKEND import strings: CACHES via CacheHandler, TASKS via TaskBackendHandler.create_connection, and MAILERS via the mailers handler. Session stores swap by setting SESSION_ENGINE to a module that defines SessionStore. — [django/core/cache/__init__.py#L36-40](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/core/cache/__init__.py#L36-L40) [django/tasks/__init__.py#L29-45](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/tasks/__init__.py#L29-L45) [django/conf/global_settings.py#L507-515](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/conf/global_settings.py#L507-L515) [django/contrib/sessions/middleware.py#L12-16](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/contrib/sessions/middleware.py#L12-L16)
- Serializers plug in through register_serializer(format, dotted_module). Built-ins cover xml, python, json, yaml, and jsonl. dumpdata/loaddata consume that registry. — [django/core/serializers/__init__.py#L26-67](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/core/serializers/__init__.py#L26-L67)
- Static-file finders plug in through STATICFILES_FINDERS. BaseFinder.find and list are the methods a custom finder must implement. Storage uses the same alias pattern (DEFAULT_STORAGE_ALIAS). — [django/contrib/staticfiles/finders.py#L18-38](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/contrib/staticfiles/finders.py#L18-L38) [django/conf/global_settings.py#L637-646](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/conf/global_settings.py#L637-L646) [django/conf/__init__.py#L25-26](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/conf/__init__.py#L25-L26)
- Password validators in the generated project are UserAttributeSimilarityValidator, MinimumLengthValidator, CommonPasswordValidator, and NumericPasswordValidator, each selected by a NAME import path. Global default AUTH_PASSWORD_VALIDATORS is an empty list; the template opts in. — [django/conf/project_template/project_name/settings.py-tpl#L86-99](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/conf/project_template/project_name/settings.py-tpl#L86-L99) [django/conf/global_settings.py#L558](https://github.com/django/django/blob/dd6f6b1531984823e3dc56740dfa93f3ceb09357/django/conf/global_settings.py#L558)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
