The codebase distinguishes core Django apps from add-on packages installed through configuration. Add-ons use a specialized application configuration class that declares metadata, compatibility bounds, and optional integration hooks. URLs mount under separate apps and legacy plugins prefixes, but the extension mechanism is conceptually unified: both provide models, views, APIs, and background behavior.
An add-on’s configuration class carries:
Declared integration entry points are conventional submodule paths resolved by import. If a submodule is absent, that feature is simply skipped. Documented categories include:
Add-ons may also ship Jinja filter modules discovered by conventional import.
A process-wide registry holds append-only stores: datasource definitions, GraphQL-capable models, homepage layout fragments, plugin-registered GraphQL types, template extensions, custom validators, metrics registrations, and similar. The registry is intended for internal and extension use, not arbitrary mutation after startup.
During application startup, each add-on:
Authors subclass a template extension base class, pinning content to a specific model identifier string. Methods on the subclass supply fragments for list views, detail views, or navigation sidebars. The core template pipeline queries registered extensions when rendering matching pages.
Add-on configuration validation enforces data types for lists and dictionaries, required settings presence, and semantic version bounds against the running platform. Misconfiguration raises explicit configuration errors at load time rather than failing mid-request.
When enabled, an add-on may reload job modules on demand for faster iteration; this trades convenience against stricter production immutability expectations.
Add-ons can subscribe to a database ready signal to defer work until models are fully installed—commonly used to register metrics after tables exist.
Beyond built-in secret storage patterns, add-ons register callable providers that resolve credential material for Git, webhooks, or external integrations using whatever vault or cloud API the enterprise prefers.
Extensions declare additional query predicates or form fields for existing model filter sets, and can augment django-tables2-style renderings so list pages show app-specific columns without forking core templates.
Qualified view names can be mapped to replacement class-based views, allowing surgical UI customization while leaving the rest of the object UI intact.
Source Application A’s extension model favors convention-over-configuration (fixed submodule paths), explicit capability flags, and central registries so operators can see what each installed package contributes. This reduces opaque monkey-patching while keeping extension surfaces broad enough for domain-specific network automation applications.