Custom Dashboard Module

In order create your own dashboard module you need to follow these steps:

Also you can always see build-in modules as examples in jet/dashboard/modules.py file and jet/dashboard/dashboard_modules/ directory on the repository.

Inherit Dashboard Module

  • Create dashboard modules file dashboard_modules.py (or any other you prefer) inside your Django application

  • Create dashboard module class inherited from base dashboard module class and add it to dashboard_modules.py file. You can see list of all available module attributes here. init_with_context method allows you to load data and initialize module’s state. You can store data in module’s fields as this instance will be passed to template.

Example of dashboard_modules.py:

from jet.dashboard.modules import DashboardModule
from contact.models import Ticket


class RecentTickets(DashboardModule):
    title = 'Recent tickets'
    title_url = Ticket.get_admin_changelist_url()
    template = 'contact/dashboard_modules/recent_tickets.html'
    limit = 10

    def init_with_context(self, context):
        self.children = Ticket.objects.order_by('-date_add')[:self.limit]
  • Optionally you can add customizable module settings and content which will be seen in administration interface. For customizable settings settings_form should be set, also settings_dict and load_settings methods should be implemented. For customizable content items child_form, child_name and child_name_plural should be set, also store_children should return True. You can validate loaded from database children in __init__ method.

_images/dashboard_module_settings.png

Example of LinkList dashboard module which has custom settings and editable list of links:

class LinkList(DashboardModule):
    title = 'Links'
    template = 'jet.dashboard/modules/link_list.html'
    layout = 'stacked'
    children = []
    settings_form = LinkListSettingsForm
    child_form = LinkListItemForm
    child_name = 'Link'
    child_name_plural = 'Links'

    def __init__(self, title=None, children=list(), **kwargs):
        children = list(map(self.parse_link, children))
        kwargs.update({'children': children})
        super(LinkList, self).__init__(title, **kwargs)

    def settings_dict(self):
        return {
            'layout': self.layout
        }

    def load_settings(self, settings):
        self.layout = settings.get('layout', self.layout)

    def store_children(self):
        return True

    def parse_link(self, link):
        if isinstance(link, (tuple, list)):
            link_dict = {'title': link[0], 'url': link[1]}
            if len(link) >= 3:
                link_dict['external'] = link[2]
            return link_dict
        elif isinstance(link, (dict,)):
            return link


class LinkListSettingsForm(forms.Form):
    layout = forms.ChoiceField(label='Layout', choices=(('stacked', 'Stacked'), ('inline', 'Inline')))


class LinkListItemForm(forms.Form):
    url = forms.CharField(label='URL')
    title = forms.CharField(label='Title')
    external = forms.BooleanField(label='External link', required=False)

Create Module Template

Create template at path specified in module class. Module instance is passed to template as module variable so you can get data directly from it.

{% load humanize %}

<ul>
    {% for ticket in module.children %}
        <li>
            <span class="float-right">
                <span class="dim">
                    {{ ticket.date_add|naturalday }} <span class="icon-clock tooltip" title="{{ ticket.date_add }}"></span>
                </span>
            </span>

            {% if ticket.forwarded %}
                <span class="icon-tick" style="color: #8ecb8e;"></span>
            {% else %}
                <span class="icon-cross" style="color: #dba4a4;"></span>
            {% endif %}

            <a href="{{ ticket.get_admin_url }}">{{ ticket.name }}</a>
        </li>
    {% empty %}
        <li>
            Nothing to show
        </li>
    {% endfor %}
</ul>

Add Module Views (Optional)

If your dashboard module needs to have own views you can register them the following way and store for example in dashboard_modules_views.py file inside your application:

from django.urls import path
from django.contrib import messages
from django.shortcuts import redirect
from jet.dashboard import dashboard
from core.utils.utils import DatabaseManager


def update_database(request):
    database_manager = DatabaseManager()
    database_manager.update_database()

    messages.success(request, 'Database was successfully updated')

    return redirect(request.META.get('HTTP_REFERER'))

# This method registers view's path
dashboard.urls.register_urls([
    path(
        'update_database/',
        update_database,
        name='update-database'
    ),
])

You should import this file before dashboard urls have been imported in you main urls.py file.

from django.conf import settings
from django.conf.urls import include
from django.urls import path

from django.contrib import admin

# Import dashboard module views
from core import dashboard_modules_views

urlpatterns = [
    path('admin/', include(admin.site.urls)),
    path('jet/', include('jet.urls', 'jet')),
    path('jet/dashboard/', include('jet.dashboard.urls', 'jet-dashboard')),
    ...
]

After that you can reverse url to module’s view this way:

{% url "jet-dashboard:update-database" %}