Sidebar Widgets¶
Added in: Milestone 2 (Phase 1A)
Sidebar widgets provide a flexible, plugin-based system for displaying auxiliary content alongside action views (like ListView). Any plugin can register widgets to appear in the sidebar.
Overview¶
The sidebar widget system allows plugins to: - Add custom UI elements to the sidebar - Display conditional content based on view context - Control widget ordering and visibility - Provide dynamic context to widget templates
SidebarWidget Dataclass¶
The SidebarWidget dataclass defines a sidebar widget:
from dataclasses import dataclass
from typing import Optional, Callable
@dataclass
class SidebarWidget:
"""Configuration for a sidebar widget."""
template: str # Path to widget template
context_callback: Optional[Callable] = None # Dynamic context provider
order: int = 100 # Display order (lower = first)
condition: Optional[Callable] = None # Display condition
identifier: Optional[str] = None # Unique ID
Attributes¶
template (required)
- Path to the widget's Django template
- Example: 'djadmin/includes/search_widget.html'
context_callback (optional)
- Callable that receives (view) and returns a dict
- Use this to add dynamic context to the widget template
- Example: lambda view: {'filterset': view.filterset}
order (optional, default: 100)
- Controls widget display order in sidebar
- Lower values appear first
- Standard values:
- 0 - Search widget
- 10 - Filter widget
- 100 - Default for custom widgets
condition (optional)
- Callable that receives (view) and returns bool
- Widget only displays if condition returns True
- Example: lambda view: hasattr(view, 'filterset')
identifier (optional) - Unique string identifier for the widget - Useful for debugging and widget management
Plugin Hook¶
Plugins register sidebar widgets via the djadmin_get_sidebar_widgets hook:
# myapp/djadmin_hooks.py
from djadmin.plugins import hookimpl
from djadmin.dataclasses import SidebarWidget
from djadmin.actions.list_view import ListAction
@hookimpl
def djadmin_get_sidebar_widgets(action):
"""Register sidebar widgets for ListView."""
def get_my_widget_context(view):
return {
'data': view.get_my_data(),
'count': view.get_my_count(),
}
def should_display(view):
return view.model_admin.my_feature_enabled
return {
ListAction: [
SidebarWidget(
template='myapp/my_widget.html',
context_callback=get_my_widget_context,
condition=should_display,
order=50,
identifier='myapp_widget',
)
]
}
Template Structure¶
Widget templates should NOT include the outer wrapper div. The sidebar rendering system adds the wrapper automatically.
❌ BAD - Don't add wrapper:
✅ GOOD - No wrapper:
{# myapp/my_widget.html #}
<h3>My Widget</h3>
<p>Widget content: {{ data }}</p>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
Built-in Widgets¶
Search Widget¶
Order: 0 (top of sidebar)
Template: djadmin/includes/search_widget.html
Condition: Only displays when search_fields is configured
Provides a search input with magnifying glass icon. Preserves other query parameters when submitting.
Filter Widget (djadmin-filters plugin)¶
Order: 10 (below search)
Template: djadmin/djadmin_filters/filter_widget.html
Condition: Only displays when filterset exists
Provides a form-based filter UI with filter fields and clear button.
Example: Custom Help Widget¶
# myapp/djadmin_hooks.py
from djadmin.plugins import hookimpl
from djadmin.dataclasses import SidebarWidget
from djadmin.actions.list_view import ListAction
@hookimpl
def djadmin_get_sidebar_widgets(action):
"""Add a help widget to ListView."""
def get_help_context(view):
return {
'model_name': view.model._meta.verbose_name,
'help_text': view.model_admin.help_text,
'doc_url': view.model_admin.doc_url,
}
def has_help_text(view):
return hasattr(view.model_admin, 'help_text')
return {
ListAction: [
SidebarWidget(
template='myapp/help_widget.html',
context_callback=get_help_context,
condition=has_help_text,
order=200, # Display after filters
identifier='help_widget',
)
]
}
{# myapp/templates/myapp/help_widget.html #}
<h3>Help</h3>
<p>{{ help_text }}</p>
{% if doc_url %}
<a href="{{ doc_url }}" target="_blank">View Documentation →</a>
{% endif %}
Accessing Widget Context in Templates¶
Widgets are available in the template context as sidebar_widgets:
{# djadmin/includes/_sidebar.html #}
<aside class="sidebar">
{% for widget in sidebar_widgets %}
<div class="sidebar-widget">
{% include widget.template %}
</div>
{% endfor %}
</aside>
The widget's context (from context_callback) is merged into the template context before rendering.
Styling¶
Sidebar widgets use the default theme's styles:
/* Sidebar layout */
.content-wrapper {
display: flex;
gap: 1.5rem;
}
.primary-content {
flex: 1;
min-width: 0;
}
.sidebar {
width: 280px;
flex-shrink: 0;
}
/* Widget container (added by sidebar rendering) */
.sidebar-widget {
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
padding: 1rem;
margin-bottom: 1rem;
}
/* Dark mode */
.dark .sidebar-widget {
background: #1f2937;
border-color: #374151;
}
See Also¶
- Column Header Icons - Add icons to column headers
- Plugin Development Guide - Creating plugins
- Hook Reference - All available hooks