Plugin System Overview¶
django-admin-deux uses djp (built on pluggy) for extensibility. Plugins allow you to add features, customize views, inject assets, and modify behavior without forking the codebase.
Why Plugins?¶
Extensibility without inheritance chains: Rather than subclassing admin classes and managing complex inheritance hierarchies, plugins let you inject functionality at specific extension points.
Composable features: Multiple plugins can coexist and combine their contributions (e.g., a search plugin + a filter plugin + an export plugin).
Clean separation: Plugins live in their own Django apps, keeping your custom logic organized and reusable across projects.
Architecture¶
Plugin Discovery¶
Plugins are Django apps that define a djadmin_hooks.py module. django-admin-deux automatically discovers plugins from INSTALLED_APPS at startup.
# myapp/djadmin_hooks.py
from djadmin.plugins import hookimpl
@hookimpl
def djadmin_provides_features():
return ['search', 'export']
@hookimpl
def djadmin_get_default_general_actions():
from .actions import ExportAction
return [ExportAction]
Key points:
- Plugin discovery is automatic (no manual registration)
- Module must be named exactly djadmin_hooks.py
- Use @hookimpl decorator to mark hook implementations
- Multiple plugins can implement the same hooks
Hook System¶
Plugins extend django-admin-deux through hooks - specific extension points where plugins can contribute functionality.
Hook types: 1. Feature advertising - Declare what features your plugin provides 2. Action hooks - Register custom actions (list, bulk, record) 3. View customization - Add mixins, modify base classes, inject attributes 4. Asset management - Contribute CSS/JS files 5. Query hooks - Modify querysets and context data
See hook-reference.md for the complete list.
Feature Validation¶
django-admin-deux validates feature requirements at startup. If a ModelAdmin uses a feature indicator (like search_fields), the corresponding feature must be provided by a registered plugin.
# This requires the 'search' feature
class BookAdmin(ModelAdmin):
search_fields = ['title', 'author__name']
If no plugin provides 'search', django-admin-deux raises ImproperlyConfigured at startup with a clear error message.
Built-in features:
- 'crud' - Provided by core plugin (always available)
- 'theme' - Provided by theme plugin (default theme)
Built-in Plugins¶
Core Plugin¶
Location: djadmin/plugins/core/
Provides:
- 'crud' feature
- Default CRUD actions (ListView, Add, Edit, Delete, Delete Selected)
- Base view mixins and context data
- Pagination helpers
Status: Always enabled (cannot be disabled)
Source: See djadmin/plugins/core/djadmin_hooks.py
Theme Plugin¶
Location: djadmin/plugins/theme/
Provides:
- 'theme' feature
- Default CSS and JavaScript assets
- Base templates and styles
Status: Auto-enabled if no alternative theme plugin is installed
Source: See djadmin/plugins/theme/djadmin_hooks.py
Plugin Use Cases¶
Common plugin patterns:
| Use Case | What to Implement |
|---|---|
| Add custom actions | djadmin_get_default_*_actions() hooks |
| Custom search | Feature + view mixins + assets |
| Export functionality | Custom action + download mixin |
| Audit logging | Lifecycle hooks (djadmin_before_action_execute) |
| Custom filters | Feature + queryset modification hook |
| Alternative theme | Feature + assets + templates |
| Bulk operations | Custom bulk actions |
| Dashboards | Dashboard hooks (future) |
Next Steps¶
- Creating Plugins - Step-by-step guide to building your first plugin
- Hook Reference - Complete list of available hooks
- Custom Actions - Creating custom actions
- Custom Themes - Theming guide
- Examples - Real-world plugin patterns
Further Reading¶
- djp documentation: https://github.com/simonw/djp
- pluggy documentation: https://pluggy.readthedocs.io/
- Project README: ../../README.md
- CLAUDE.md: ../../CLAUDE.md - Project development guide