Commits

David Jean Louis committed c37885f

work on customization API

Comments (0)

Files changed (8)

admin_tools/dashboard/default_dashboard.py

+"""
+django-admin-tools default dashboards.
+"""
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+from admin_tools.dashboard.models import *
+
+
+class DefaultIndexDashboard(Dashboard):
+    """
+    Default admin index dashboard.
+    """ 
+    def __init__(self, *args, **kwargs):
+        super(DefaultIndexDashboard, self).__init__(*args, **kwargs)
+
+        # append a link list module for "quick links"
+        self.append(LinkListDashboardModule(
+            title=_('Quick links'),
+            layout='inline',
+            draggable=False,
+            deletable=False,
+            collapsible=False,
+            link_list=[
+                {
+                    'title': _('Return to site'),
+                    'url': '/',
+                },
+                {
+                    'title': _('Change password'),
+                    'url': reverse('admin:password_change'),
+                },
+                {
+                    'title': _('Log out'),
+                    'url': reverse('admin:logout')
+                },
+            ]
+        ))
+
+        # append an app list module for "Applications"
+        self.append(AppListDashboardModule(
+            title=_('Applications'),
+            exclude_list=('django.contrib',),
+        ))
+
+        # append an app list module for "Administration"
+        self.append(AppListDashboardModule(
+            title=_('Administration'),
+            include_list=('django.contrib',),
+        ))
+
+        # append a recent actions module
+        self.append(RecentActionsDashboardModule(
+            enabled=False,
+            title=_('Recent Actions'),
+            limit=5
+        ))
+
+        # append a feed module
+        self.append(FeedDashboardModule(
+            enabled=False,
+            title=_('Latest Django News'),
+            feed_url='http://www.djangoproject.com/rss/weblog/',
+            limit=5
+        ))
+
+        # append another link list module for "support". 
+        self.append(LinkListDashboardModule(
+            title=_('Support'),
+            link_list=[
+                {
+                    'title': _('Django documentation'),
+                    'url': 'http://docs.djangoproject.com/',
+                    'external': True,
+                },
+                {
+                    'title': _('Django "django-users" mailing list'),
+                    'url': 'http://groups.google.com/group/django-users',
+                    'external': True,
+                },
+                {
+                    'title': _('Django irc channel'),
+                    'url': 'irc://irc.freenode.net/django',
+                    'external': True,
+                },
+            ]
+        ))
+
+
+class DefaultAppIndexDashboard(AppIndexDashboard):
+    """
+    Default admin app index dashboard.
+    """
+    def __init__(self, *args, **kwargs):
+        super(DefaultAppIndexDashboard, self).__init__(*args, **kwargs)
+
+        # we disable title because its redundant with the model list module
+        self.title = ''
+
+        # append a model list module
+        self.append(ModelListDashboardModule(
+            title=self.app_title,
+            include_list=self.models,
+        ))
+
+        # append a recent actions module
+        self.append(RecentActionsDashboardModule(
+            title=_('Recent Actions'),
+            include_list=self.models,
+            limit=5
+        ))

admin_tools/dashboard/management/commands/customdashboard.py

 import os, shutil
 from optparse import make_option
-from django.core.management.base import BaseCommand, CommandError
+from django.core.management.base import BaseCommand, LabelCommand, CommandError
+from django.template.loader import render_to_string
 
 
+DEFAULT_FILE = 'dashboard.py'
+
 class Command(BaseCommand):
     option_list = BaseCommand.option_list + (
         make_option(
             '-f',
             '--file',
             help='The file path where the base code should be written (default: dashboard.py)',
-            default='dashboard.py',
+            default=DEFAULT_FILE,
         ),
     )
-    help = 'Creates a template file containing the base code to get you \
-            started with your custom dashboard'
-    args = '[file]'
+    help = ('Creates a template file containing the base code to get you '
+            'started with your custom dashboard.')
+    args = '[appname]'
+    label = 'application name'
 
-    def handle(self, **options):
-        project_name = os.path.basename(os.getcwd())
-        src = os.path.join(os.path.dirname(__file__), '..', '..', 'templates', 'dashboard.txt')
-        dst = os.path.join(options['file'])
+    def handle(self, appname=None, **options):
+        context = {}
+        context['project'] = os.path.basename(os.getcwd())
+        if appname:
+            tpl = 'dashboard/dashboard_app_index.txt'
+            if not os.path.exists(appname):
+                raise CommandError('application "%s" not found' % appname)
+            dst = os.path.join(appname, options['file'])
+            context['app'] = appname
+            if options['file'] != DEFAULT_FILE:
+                context['warning'] = True
+        else:
+            tpl = 'dashboard/dashboard.txt'
+            dst = os.path.join(options['file'])
         if os.path.exists(dst):
-            raise CommandError('Error: file "%s" already exists' % dst)
-        open(dst, 'w').write(open(src).read() % {
-            'project': project_name,
-            'file': os.path.basename(options['file']).split('.')[0]
-        })
+            raise CommandError('file "%s" already exists' % dst)
+        context['file'] = os.path.basename(dst).split('.')[0]
+        open(dst, 'w').write(render_to_string(tpl, context))
         print '"%s" written.' % os.path.join(options['file'])
 

admin_tools/dashboard/models.py

     >>> len(d)
     1
     """
-
     class Media:
         css = {
             'all': 'dashboard.css',
         self.columns = kwargs.get('columns', 2)
 
 
+class AppIndexDashboard(Dashboard):
+    """
+    Class that represents an app index dashboard, it is very similar to the 
+    standard dashboard except that its constructors receives two arguments:
+
+    ``app_title``
+        The title of the application
+
+    ``models``
+        A list of strings representing the available models for the current 
+        application, example::
+            
+            ['yourproject.app.Model1', 'yourproject.app.Model2']
+
+    If you want to provide custom app index dashboard, be sure to inherit from
+    this class instead of the ``Dashboard`` class.
+    """
+    def __init__(self, app_title, models, *args, **kwargs):
+        super(AppIndexDashboard, self).__init__(*args, **kwargs)
+        self.app_title = app_title
+        self.models = models
+
 class DashboardModule(object):
     """
     Base class for all dashboard modules.

admin_tools/dashboard/templates/dashboard/dashboard.txt

+from django.utils.translation import ugettext_lazy as _
+from django.core.urlresolvers import reverse
+from admin_tools.dashboard.models import *
+
+# create your custom modules here if you want, for example:
+#
+# class CustomDashboardModule(DashboardModule):
+#     pass
+#
+
+
+# to activate your index dashboard you must add the following to your 
+# project's settings.py file:
+#
+# ADMIN_TOOLS_INDEX_DASHBOARD = '{{ project }}.{{ file }}.CustomIndexDashboard'
+class CustomIndexDashboard(Dashboard):
+    """
+    Document your custom dashboard.
+    """ 
+    def __init__(self, *args, **kwargs):
+        super(CustomIndexDashboard, self).__init__(*args, **kwargs)
+
+        # append your modules here, example:
+        self.append(AppListDashboardModule(
+            title=_('Modules'),
+        ))
+        self.append(RecentActionsDashboardModule(
+            title=_('Recent Actions'),
+            limit=5
+        ))
+
+
+# to activate your app index dashboard you must add the following to your 
+# project's settings.py file:
+#
+# ADMIN_TOOLS_APP_INDEX_DASHBOARD = '{{ project }}.{{ file }}.CustomAppIndexDashboard'
+class CustomAppIndexDashboard(AppIndexDashboard):
+    """
+    Document your custom app index dashboard.
+    """ 
+    def __init__(self, app_title, models, *args, **kwargs):
+        super(CustomAppIndexDashboard, self).__init__(*args, **kwargs)
+
+        # append your modules here, example:
+        self.append(AppListDashboardModule(
+            title=_('Modules'),
+            include_list=models,
+        ))
+        self.append(RecentActionsDashboardModule(
+            title=_('Recent Actions'),
+            limit=5,
+            include_list=models,
+        ))

admin_tools/dashboard/templates/dashboard/dashboard_app_index.txt

+from django.utils.translation import ugettext_lazy as _
+from django.core.urlresolvers import reverse
+from admin_tools.dashboard.models import *
+
+# create your custom modules here if you want, for example:
+#
+# class CustomDashboardModule(DashboardModule):
+#     pass
+#
+{% if warning %}
+# WARNING: you've changed the default file name 'dashboard.py' to '{{ file }}.py',
+# so, you will need to tell django-admin-tools about this, just add this line
+# to your settings.py file:
+# ADMIN_TOOLS_APP_INDEX_DASHBOARD_MODULE = '{{ file }}'
+{% endif %}
+# Your {{ app }} dashboard class
+class {{ app|capfirst }}Dashboard(AppIndexDashboard):
+    """
+    Document your custom app index dashboard.
+    """ 
+    def __init__(self, app_title, models, *args, **kwargs):
+        super(CustomAppIndexDashboard, self).__init__(*args, **kwargs)
+
+        # append your modules here, example:
+        # self.append(RecentActionsDashboardModule(
+        #     title=_('Recent Actions'),
+        #     limit=5,
+        #     include_list=models,
+        # ))

admin_tools/dashboard/utils.py

 from django.contrib import admin
 from django.core.urlresolvers import reverse
 from django.http import HttpRequest
+from django.utils.importlib import import_module
 from django.utils.text import capfirst
 from django.utils.translation import ugettext_lazy as _
 from admin_tools.dashboard.models import *
+from admin_tools.dashboard.default_dashboard import *
 
 
 def get_dashboard_from_context(context):
         return get_index_dashboard(request)
     try:
         app = context['app_list'][0]
-        model_list = []
+        models = []
+        app_label = app['name']
         for model, model_admin in admin.site._registry.items():
             if app['name'] == model._meta.app_label.title():
+                app_label = model._meta.app_label
                 for m in app['models']:
                     if m['name'] == capfirst(model._meta.verbose_name_plural):
                         mod = '%s.%s' % (model.__module__, model.__name__)
-                        model_list.append(mod)
-        return get_app_index_dashboard(request, app['name'], model_list)
+                        models.append(mod)
+        return get_app_index_dashboard(request, app_label, models)
     except KeyError:
-        return get_app_index_dashboard(request)
+        return get_app_index_dashboard(request, '', [])
 
 
 def get_index_dashboard(request):
     """
     Returns the admin dashboard defined by the user or the default one.
     """
-    provider = getattr(settings, 'ADMIN_TOOLS_INDEX_DASHBOARD_PROVIDER', False)
-    if provider:
-        from django.utils.importlib import import_module
-        mod, inst = provider.rsplit('.', 1)
+    dashboard_cls = getattr(settings, 'ADMIN_TOOLS_INDEX_DASHBOARD', False)
+    if dashboard_cls:
+        mod, inst = dashboard_cls.rsplit('.', 1)
         mod = import_module(mod)
         return getattr(mod, inst)()
+    return DefaultIndexDashboard()
 
-    index_dashboard = Dashboard()
-    index_dashboard.append(LinkListDashboardModule(
-        title=_('Quick links'),
-        layout='inline',
-        draggable=False,
-        deletable=False,
-        collapsible=False,
-        link_list=[
-            {
-                'title': _('Return to site'),
-                'url': '/',
-            },
-            {
-                'title': _('Change password'),
-                'url': reverse('admin:password_change'),
-            },
-            {
-                'title': _('Log out'),
-                'url': reverse('admin:logout')
-            },
-        ]
-    ))
-    index_dashboard.append(AppListDashboardModule(
-        title=_('Applications'),
-        exclude_list=('django.contrib',),
-    ))
-    index_dashboard.append(AppListDashboardModule(
-        title=_('Administration'),
-        include_list=('django.contrib',),
-    ))
-    index_dashboard.append(RecentActionsDashboardModule(
-        enabled=False,
-        title=_('Recent Actions'),
-        limit=5
-    ))
-    index_dashboard.append(FeedDashboardModule(
-        enabled=False,
-        title=_('Latest Django News'),
-        feed_url='http://www.djangoproject.com/rss/weblog/',
-        limit=5
-    ))
-    index_dashboard.append(LinkListDashboardModule(
-        title=_('Support'),
-        link_list=[
-            {
-                'title': _('Django documentation'),
-                'url': 'http://docs.djangoproject.com/',
-                'external': True,
-            },
-            {
-                'title': _('Django "django-users" mailing list'),
-                'url': 'http://groups.google.com/group/django-users',
-                'external': True,
-            },
-            {
-                'title': _('Django irc channel'),
-                'url': 'irc://irc.freenode.net/django',
-                'external': True,
-            },
-        ]
-    ))
-    return index_dashboard
 
-
-def get_app_index_dashboard(request, app_title='', model_list=[]):
+def get_app_index_dashboard(request, app_label='', model_list=[]):
     """
     Returns the admin dashboard defined by the user or the default one.
     """
-    provider = getattr(settings, 'ADMIN_TOOLS_APP_INDEX_DASHBOARD_PROVIDER', False)
-    if provider:
-        from django.utils.importlib import import_module
-        mod, inst = provider.rsplit('.', 1)
+    app_title = app_label.title()
+
+    # try to discover corresponding app dashboard module
+    mod_name = getattr(settings, 'ADMIN_TOOLS_APP_INDEX_DASHBOARD_MODULE', 'dashboard')
+    mod_class = getattr(settings, 'ADMIN_TOOLS_APP_INDEX_DASHBOARD_CLASS', '%sDashboard' % capfirst(app_label))
+    try:
+        mod = import_module('%s.%s' % (app_label, mod_name))
+        return getattr(mod, mod_class)(app_title, model_list)
+    except:
+        pass
+
+    # try to discover a general app_index dashboard
+    dashboard_cls = getattr(settings, 'ADMIN_TOOLS_APP_INDEX_DASHBOARD', False)
+    if dashboard_cls:
+        mod, inst = dashboard_cls.rsplit('.', 1)
         mod = import_module(mod)
-        return getattr(mod, inst)(app_name)
+        return getattr(mod, inst)(app_title, model_list)
 
-    app_index_dashboard = Dashboard(title='')
-    app_index_dashboard.append(ModelListDashboardModule(
-        title=app_title,
-        include_list=model_list,
-    ))
-    app_index_dashboard.append(RecentActionsDashboardModule(
-        title=_('Recent Actions'),
-        include_list=model_list,
-        limit=5
-    ))
-    return app_index_dashboard
+    # fallback to default dashboard
+    return DefaultAppIndexDashboard(app_title, model_list)

admin_tools/menu/management/commands/custommenu.py

 import os, shutil
 from optparse import make_option
 from django.core.management.base import BaseCommand, CommandError
+from django.template.loader import render_to_string
 
 
 class Command(BaseCommand):
             default='menu.py',
         ),
     )
-    help = 'Creates a template file containing the base code to get you \
-            started with your custom menu'
-    args = '[file]'
+    help = ('Creates a template file containing the base code to get you '
+            'started with your custom menu')
 
     def handle(self, **options):
         project_name = os.path.basename(os.getcwd())
-        src = os.path.join(os.path.dirname(__file__), '..', '..', 'templates', 'menu.txt')
         dst = os.path.join(options['file'])
         if os.path.exists(dst):
             raise CommandError('Error: file "%s" already exists' % dst)
-        open(dst, 'w').write(open(src).read() % {
+        open(dst, 'w').write(render_to_string('menu/menu.txt', {
             'project': project_name,
             'file': os.path.basename(options['file']).split('.')[0]
-        })
+        }))
         print '"%s" written.' % os.path.join(options['file'])
 

admin_tools/menu/utils.py

 from django.conf import settings
 from django.core.urlresolvers import reverse
 from django.utils.translation import ugettext_lazy as _
+from django.utils.importlib import import_module
 from admin_tools.menu.models import Menu, MenuItem, AppListMenuItem
 
 
     """
     Returns the admin menu defined by the user or the default one.
     """
-    provider = getattr(settings, 'ADMIN_TOOLS_INDEX_MENU_PROVIDER', False)
-    if provider:
-        from django.utils.importlib import import_module
-        mod, inst = provider.rsplit('.', 1)
+    menu_cls = getattr(settings, 'ADMIN_TOOLS_MENU', False)
+    if menu_cls:
+        mod, inst = menu_cls.rsplit('.', 1)
         mod = import_module(mod)
         return getattr(mod, inst)()