greatly improved documentation, better customization API
|
@ -0,0 +1,62 @@
|
|||
"""
|
||||
Dashboard registry.
|
||||
"""
|
||||
|
||||
from admin_tools.dashboard.models import Dashboard
|
||||
|
||||
class Registry(object):
|
||||
"""
|
||||
Registry for application dashboards.
|
||||
"""
|
||||
registry = {}
|
||||
|
||||
def register(cls, klass, app_name):
|
||||
if not issubclass(klass, Dashboard):
|
||||
raise ValueError('%s is not an instance of Dashboard' % klass)
|
||||
if app_name in cls.registry:
|
||||
raise ValueError('A dashboard has already been registered for '
|
||||
'the application "%s"', app_name)
|
||||
cls.registry[app_name] = klass
|
||||
register = classmethod(register)
|
||||
|
||||
|
||||
def register(cls, *args, **kwargs):
|
||||
"""
|
||||
Register a custom dashboard into the global registry.
|
||||
"""
|
||||
Registry.register(cls, *args, **kwargs)
|
||||
|
||||
|
||||
def autodiscover(blacklist=[]):
|
||||
"""
|
||||
Automagically discover custom dashboards and menus for installed apps.
|
||||
Optionally you can pass a ``blacklist`` of apps that you don't want to
|
||||
provide their own app index dashboard.
|
||||
"""
|
||||
import imp
|
||||
from django.conf import settings
|
||||
from django.utils.importlib import import_module
|
||||
|
||||
blacklist.append('admin_tools.dashboard')
|
||||
blacklist.append('admin_tools.menu')
|
||||
blacklist.append('admin_tools.theming')
|
||||
|
||||
for app in settings.INSTALLED_APPS:
|
||||
# skip blacklisted apps
|
||||
if app in blacklist:
|
||||
continue
|
||||
|
||||
# try to import the app
|
||||
try:
|
||||
app_path = import_module(app).__path__
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
# try to find a app.dashboard module
|
||||
try:
|
||||
imp.find_module('dashboard', app_path)
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
# looks like we found it so import it !
|
||||
import_module('%s.dashboard' % app)
|
|
@ -1,111 +0,0 @@
|
|||
"""
|
||||
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,
|
||||
entries=[
|
||||
{
|
||||
'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'),
|
||||
entries=[
|
||||
{
|
||||
'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
|
||||
))
|
|
@ -12,22 +12,65 @@ from admin_tools.utils import AppListElementMixin
|
|||
class Dashboard(list):
|
||||
"""
|
||||
Base class for dashboards.
|
||||
The Dashboard class is a simple python list that takes three optional
|
||||
keywords arguments ``title``, ``template`` and ``columns``.
|
||||
The Dashboard class is a simple python list that has three additional
|
||||
properties:
|
||||
|
||||
>>> d = Dashboard(template='foo.html', columns=3)
|
||||
>>> d.template
|
||||
'foo.html'
|
||||
>>> d.columns
|
||||
3
|
||||
>>> d.append(DashboardModule())
|
||||
>>> d.append(DashboardModule())
|
||||
>>> len(d)
|
||||
2
|
||||
>>> d.pop().__class__.__name__
|
||||
'DashboardModule'
|
||||
>>> len(d)
|
||||
1
|
||||
``title``
|
||||
The dashboard title, by default, it is displayed above the dashboard
|
||||
in a ``h2`` tag. Default value: 'Dashboard'.
|
||||
|
||||
``template``
|
||||
The template to use to render the dashboard.
|
||||
Default value: 'dashboard/dashboard.html'
|
||||
|
||||
``columns``
|
||||
An integer that represents the number of columns for the dashboard.
|
||||
Default value: 2.
|
||||
|
||||
If you want to customize the look of your dashboard and it's modules, you
|
||||
can declare css stylesheets and/or javascript files to include when
|
||||
rendering the dashboard, for example::
|
||||
|
||||
from admin_tools.dashboard.models import *
|
||||
|
||||
class MyDashboard(Dashboard):
|
||||
class Media:
|
||||
css = {'screen': '/media/css/mydashboard.css'}
|
||||
js = ('/media/js/mydashboard.js',)
|
||||
|
||||
Here's an example of a custom dashboard::
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from admin_tools.dashboard.models import *
|
||||
|
||||
class MyDashboard(Dashboard):
|
||||
def render(self, request):
|
||||
# we want a 3 columns layout
|
||||
self.columns = 3
|
||||
|
||||
# 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
|
||||
))
|
||||
|
||||
Below is a screenshot of the resulting dashboard:
|
||||
|
||||
.. image:: images/dashboard_example.png
|
||||
"""
|
||||
class Media:
|
||||
css = {
|
||||
|
@ -44,29 +87,29 @@ class Dashboard(list):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Dashboard constructor, keyword argument:
|
||||
|
||||
``title``
|
||||
the title to display for your dashboard.
|
||||
Default value: 'Dashboard'.
|
||||
|
||||
``template``
|
||||
the path to the dashboard template.
|
||||
Default value: 'dashboard/dashboard.html'.
|
||||
|
||||
``columns``
|
||||
The number of columns for the dashboard. Default value: 2.
|
||||
Dashboard constructor.
|
||||
"""
|
||||
super(Dashboard, self).__init__()
|
||||
self.title = kwargs.get('title', _('Dashboard'))
|
||||
self.template = kwargs.get('template', 'dashboard/dashboard.html')
|
||||
self.columns = kwargs.get('columns', 2)
|
||||
|
||||
def render(self, request):
|
||||
"""
|
||||
The ``Dashboard.render()`` method is called just before the display
|
||||
with a ``django.http.HttpRequest`` as unique argument.
|
||||
Override this method to build your dashboard if you need to access to
|
||||
the request instance.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
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:
|
||||
Class that represents an app index dashboard, app index dashboards are
|
||||
displayed in the applications index page.
|
||||
``AppIndexDashboard`` is very similar to the ``Dashboard`` class except
|
||||
that its constructor receives two extra arguments:
|
||||
|
||||
``app_title``
|
||||
The title of the application
|
||||
|
@ -79,64 +122,92 @@ class AppIndexDashboard(Dashboard):
|
|||
|
||||
If you want to provide custom app index dashboard, be sure to inherit from
|
||||
this class instead of the ``Dashboard`` class.
|
||||
|
||||
Here's an example of a custom app index dashboard::
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from admin_tools.dashboard.models import *
|
||||
|
||||
class MyAppIndexDashboard(AppIndexDashboard):
|
||||
def render(self, request):
|
||||
# we don't want a title, it's redundant
|
||||
self.title = ''
|
||||
|
||||
# append a model list module that lists all models
|
||||
# for the app
|
||||
self.append(ModelListDashboardModule(
|
||||
title=self.app_title,
|
||||
include_list=self.models,
|
||||
))
|
||||
|
||||
# append a recent actions module for the current app
|
||||
self.append(RecentActionsDashboardModule(
|
||||
title=_('Recent Actions'),
|
||||
include_list=self.models,
|
||||
limit=5
|
||||
))
|
||||
|
||||
Below is a screenshot of the resulting dashboard:
|
||||
|
||||
.. image:: images/dashboard_app_index_example.png
|
||||
"""
|
||||
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.
|
||||
Dashboard modules have the following properties:
|
||||
|
||||
``enabled``
|
||||
Boolean that determines whether the module should be enabled in
|
||||
the dashboard by default or not. Default value: ``True``.
|
||||
|
||||
``draggable``
|
||||
Boolean that determines whether the module can be draggable or not.
|
||||
Draggable modules can be re-arranged by users. Default value: ``True``.
|
||||
|
||||
``collapsible``
|
||||
Boolean that determines whether the module is collapsible, this
|
||||
allows users to show/hide module content. Default: ``True``.
|
||||
|
||||
``deletable``
|
||||
Boolean that determines whether the module can be removed from the
|
||||
dashboard by users or not. Default: ``True``.
|
||||
|
||||
``title``
|
||||
String that contains the module title, make sure you use the django
|
||||
gettext functions if your application is multilingual.
|
||||
Default value: ''.
|
||||
|
||||
``title_url``
|
||||
String that contains the module title URL. If given the module
|
||||
title will be a link to this URL. Default value: ``None``.
|
||||
|
||||
``css_classes``
|
||||
A list of css classes to be added to the module ``div`` class
|
||||
attribute. Default value: ``None``.
|
||||
|
||||
``pre_content``
|
||||
Text or HTML content to display above the module content.
|
||||
Default value: ``None``.
|
||||
|
||||
``content``
|
||||
The module text or HTML content. Default value: ``None``.
|
||||
|
||||
``post_content``
|
||||
Text or HTML content to display under the module content.
|
||||
Default value: ``None``.
|
||||
|
||||
``template``
|
||||
The template to use to render the module.
|
||||
Default value: 'dashboard/module.html'.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Dashboard module constructor, keywords arguments (all are optional):
|
||||
|
||||
``enabled``
|
||||
Boolean that determines whether the module should be enabled in
|
||||
the dashboard by default or not. Default value: True.
|
||||
|
||||
``draggable``
|
||||
Boolean that determines whether the module can be draggable or not.
|
||||
Draggable modules can be re-arranged by users. Default value: True.
|
||||
|
||||
``collapsible``
|
||||
Boolean that determines whether the module is collapsible, this
|
||||
allows users to show/hide module content. Default: True.
|
||||
|
||||
``deletable``
|
||||
Boolean that determines whether the module can be removed from the
|
||||
dashboard by users or not. Default: True.
|
||||
|
||||
``title``
|
||||
String that contains the module title, make sure you use the django
|
||||
gettext functions if your application is multilingual.
|
||||
Default value: ''.
|
||||
|
||||
``title_url``
|
||||
String that contains the module title URL. If given the module
|
||||
title will be a link to this URL. Default value: None.
|
||||
|
||||
``css_classes``
|
||||
A list of css classes to be added to the module ``div`` class
|
||||
attribute. Default value: None.
|
||||
|
||||
``pre_content``
|
||||
Text or HTML content to display above the module content.
|
||||
Default value: None.
|
||||
|
||||
``content``
|
||||
The module text or HTML content. Default value: None.
|
||||
|
||||
``post_content``
|
||||
Text or HTML content to display under the module content.
|
||||
Default value: None.
|
||||
|
||||
``template``
|
||||
The template to use to render the module.
|
||||
Default value: 'dashboard/module.html'.
|
||||
"""
|
||||
self.enabled = kwargs.get('enabled', True)
|
||||
self.draggable = kwargs.get('draggable', True)
|
||||
self.collapsible = kwargs.get('collapsible', True)
|
||||
|
@ -204,19 +275,62 @@ class DashboardModule(object):
|
|||
return ' '.join(ret)
|
||||
|
||||
|
||||
class TextDashboardModule(DashboardModule):
|
||||
"""
|
||||
Dashboard module that displays a list of links.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TextDashboardModule, self).__init__(*args, **kwargs)
|
||||
self.entries.append(kwargs.get('text', ''))
|
||||
|
||||
|
||||
class LinkListDashboardModule(DashboardModule):
|
||||
"""
|
||||
Dashboard module that displays a list of links.
|
||||
A module that displays a list of links.
|
||||
As well as the ``DashboardModule`` properties, the
|
||||
``LinkListDashboardModule`` takes an extra keyword argument:
|
||||
|
||||
``layout``
|
||||
The layout of the list, possible values are ``stacked`` and ``inline``.
|
||||
The default value is ``stacked``.
|
||||
|
||||
Link list modules entries are simple python dictionaries that can have the
|
||||
following keys:
|
||||
|
||||
``title``
|
||||
The link title.
|
||||
|
||||
``url``
|
||||
The link URL.
|
||||
|
||||
``external``
|
||||
Boolean that indicates whether the link is an external one or not.
|
||||
|
||||
``description``
|
||||
A string describing the link, it will be the ``title`` attribute of
|
||||
the html ``a`` tag.
|
||||
|
||||
Here's a small example of building a link list module::
|
||||
|
||||
from admin_tools.dashboard.models import *
|
||||
|
||||
mydashboard = Dashboard()
|
||||
mydashboard.append(LinkListDashboardModule(
|
||||
layout='inline',
|
||||
entries=(
|
||||
{
|
||||
'title': 'Python website',
|
||||
'url': 'http://www.python.org',
|
||||
'external': True,
|
||||
'title': 'Python programming language rocks !',
|
||||
},
|
||||
{
|
||||
'title': 'Django website',
|
||||
'url': 'http://www.djangoproject.com',
|
||||
'external': True
|
||||
},
|
||||
{
|
||||
'title': 'Some internal link',
|
||||
'url': '/some/internal/link/',
|
||||
'external': False
|
||||
},
|
||||
)
|
||||
))
|
||||
|
||||
The screenshot of what this code produces:
|
||||
|
||||
.. image:: images/linklist_dashboard_module.png
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -229,22 +343,63 @@ class LinkListDashboardModule(DashboardModule):
|
|||
|
||||
class AppListDashboardModule(DashboardModule, AppListElementMixin):
|
||||
"""
|
||||
Class that represents a dashboard module that lists installed apps.
|
||||
Module that lists installed apps and their models.
|
||||
As well as the ``DashboardModule`` properties, the
|
||||
``AppListDashboardModule`` has two extra properties:
|
||||
|
||||
``exclude_list``
|
||||
A list of apps to exclude, if an app name (e.g. "django.contrib.auth"
|
||||
starts with an element of this list (e.g. "django.contrib") it won't
|
||||
appear in the dashboard module.
|
||||
|
||||
``include_list``
|
||||
A list of apps to include, only apps whose name (e.g.
|
||||
"django.contrib.auth") starts with one of the strings (e.g.
|
||||
"django.contrib") in the list will appear in the dashboard module.
|
||||
|
||||
If no include/exclude list is provided, **all apps** are shown.
|
||||
|
||||
Here's a small example of building an app list module::
|
||||
|
||||
from admin_tools.dashboard.models import *
|
||||
|
||||
mydashboard = Dashboard()
|
||||
|
||||
# will only list the django.contrib apps
|
||||
mydashboard.append(AppListDashboardModule(
|
||||
title='Administration',
|
||||
include_list=('django.contrib',)
|
||||
))
|
||||
# will list all apps except the django.contrib ones
|
||||
mydashboard.append(AppListDashboardModule(
|
||||
title='Applications',
|
||||
exclude_list=('django.contrib',)
|
||||
))
|
||||
|
||||
The screenshot of what this code produces:
|
||||
|
||||
.. image:: images/applist_dashboard_module.png
|
||||
|
||||
.. note::
|
||||
|
||||
Note that this module takes into account user permissions, for
|
||||
example, if a user has no rights to change or add a ``Group``, then
|
||||
the django.contrib.auth.Group model line will not be displayed.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AppListDashboardModule, self).__init__(*args, **kwargs)
|
||||
self.title = kwargs.get('title', _('Applications'))
|
||||
self.include_list = kwargs.get('include_list', [])
|
||||
self.exclude_list = kwargs.get('exclude_list', [])
|
||||
self.template = kwargs.get('template',
|
||||
'dashboard/modules/app_list.html')
|
||||
self.include_list = kwargs.get('include_list', [])
|
||||
self.exclude_list = kwargs.get('exclude_list', [])
|
||||
|
||||
def render(self, request):
|
||||
apps = {}
|
||||
for model, model_admin in admin.site._registry.items():
|
||||
perms = self._check_perms(request, model, model_admin)
|
||||
if not perms:
|
||||
if not perms or ('add' not in perms and 'change' not in perms):
|
||||
continue
|
||||
app_label = model._meta.app_label
|
||||
if app_label not in apps:
|
||||
|
@ -270,14 +425,50 @@ class AppListDashboardModule(DashboardModule, AppListElementMixin):
|
|||
|
||||
|
||||
class ModelListDashboardModule(DashboardModule, AppListElementMixin):
|
||||
"""
|
||||
Module that lists a set of models.
|
||||
As well as the ``DashboardModule`` properties, the
|
||||
``ModelListDashboardModule`` takes two extra keyword arguments:
|
||||
|
||||
``include_list``
|
||||
A list of models to include, only models whose name (e.g.
|
||||
"blog.comments.Comment") starts with one of the strings (e.g. "blog")
|
||||
in the include list will appear in the dashboard module.
|
||||
|
||||
``exclude_list``
|
||||
A list of models to exclude, if a model name (e.g.
|
||||
"blog.comments.Comment" starts with an element of this list (e.g.
|
||||
"blog.comments") it won't appear in the dashboard module.
|
||||
|
||||
Here's a small example of building a model list module::
|
||||
|
||||
from admin_tools.dashboard.models import *
|
||||
|
||||
mydashboard = Dashboard()
|
||||
# will only list the django.contrib.auth models
|
||||
mydashboard.append(ModelListDashboardModule(
|
||||
title='Authentication',
|
||||
include_list=('django.contrib.auth',)
|
||||
))
|
||||
|
||||
The screenshot of what this code produces:
|
||||
|
||||
.. image:: images/recentactions_dashboard_module.png
|
||||
|
||||
.. note::
|
||||
|
||||
Note that this module takes into account user permissions, for
|
||||
example, if a user has no rights to change or add a ``Group``, then
|
||||
the django.contrib.auth.Group model line will not be displayed.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ModelListDashboardModule, self).__init__(*args, **kwargs)
|
||||
self.title = kwargs.get('title', '')
|
||||
self.include_list = kwargs.get('include_list', [])
|
||||
self.exclude_list = kwargs.get('exclude_list', [])
|
||||
self.template = kwargs.get('template',
|
||||
'dashboard/modules/model_list.html')
|
||||
self.include_list = kwargs.get('include_list', [])
|
||||
self.exclude_list = kwargs.get('exclude_list', [])
|
||||
|
||||
def render(self, request):
|
||||
for model, model_admin in admin.site._registry.items():
|
||||
|
@ -299,16 +490,47 @@ class ModelListDashboardModule(DashboardModule, AppListElementMixin):
|
|||
class RecentActionsDashboardModule(DashboardModule):
|
||||
"""
|
||||
Module that lists the recent actions for the current user.
|
||||
As well as the ``DashboardModule`` properties, the
|
||||
``RecentActionsDashboardModule`` takes three extra keyword arguments:
|
||||
|
||||
``include_list``
|
||||
A list of models to include, only actions for models whose name (e.g.
|
||||
"blog.comments.Comment") starts with one of the strings (e.g. "blog")
|
||||
in the include list will appear in the dashboard module.
|
||||
|
||||
``exclude_list``
|
||||
A list of models to exclude, if a model name (e.g.
|
||||
"blog.comments.Comment" starts with an element of this list (e.g.
|
||||
"blog.comments") it's recent actions won't appear in the dashboard
|
||||
module.
|
||||
|
||||
``limit``
|
||||
The maximum number of entries to display. Default value: 10.
|
||||
|
||||
Here's a small example of building a recent actions module::
|
||||
|
||||
from admin_tools.dashboard.models import *
|
||||
|
||||
mydashboard = Dashboard()
|
||||
# will only list the django.contrib apps
|
||||
mydashboard.append(RecentActionsDashboardModule(
|
||||
title='Django CMS recent actions',
|
||||
include_list=('cms',)
|
||||
))
|
||||
|
||||
The screenshot of what this code produces:
|
||||
|
||||
.. image:: images/recentactions_dashboard_module.png
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RecentActionsDashboardModule, self).__init__(*args, **kwargs)
|
||||
self.title = kwargs.get('title', _('Recent Actions'))
|
||||
self.include_list = kwargs.get('include_list', [])
|
||||
self.exclude_list = kwargs.get('exclude_list', [])
|
||||
self.limit = kwargs.get('limit', [])
|
||||
self.template = kwargs.get('template',
|
||||
'dashboard/modules/recent_actions.html')
|
||||
self.include_list = kwargs.get('include_list', [])
|
||||
self.exclude_list = kwargs.get('exclude_list', [])
|
||||
self.limit = kwargs.get('limit', 10)
|
||||
|
||||
def render(self, request):
|
||||
from django.contrib.admin.models import LogEntry
|
||||
|
@ -327,6 +549,39 @@ class RecentActionsDashboardModule(DashboardModule):
|
|||
class FeedDashboardModule(DashboardModule):
|
||||
"""
|
||||
Class that represents a feed dashboard module.
|
||||
|
||||
.. important::
|
||||
|
||||
This class uses the
|
||||
`Universal Feed Parser module <http://www.feedparser.org/>`_ to parse
|
||||
the feeds, so you'll need to install it, all feeds supported by
|
||||
FeedParser are thus supported by the FeedDashboardModule.
|
||||
|
||||
As well as the ``DashboardModule`` properties, the ``FeedDashboardModule``
|
||||
takes two extra keyword arguments:
|
||||
|
||||
``feed_url``
|
||||
The URL of the feed.
|
||||
|
||||
``limit``
|
||||
The maximum number of feed entries to display. Default value: None,
|
||||
which means that all entries are displayed.
|
||||
|
||||
Here's a small example of building a recent actions module::
|
||||
|
||||
from admin_tools.dashboard.models import *
|
||||
|
||||
mydashboard = Dashboard()
|
||||
# will only list the django.contrib apps
|
||||
mydashboard.append(FeedDashboardModule(
|
||||
title=_('Latest Django News'),
|
||||
feed_url='http://www.djangoproject.com/rss/weblog/',
|
||||
limit=5
|
||||
))
|
||||
|
||||
The screenshot of what this code produces:
|
||||
|
||||
.. image:: images/feed_dashboard_module.png
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FeedDashboardModule, self).__init__(*args, **kwargs)
|
||||
|
@ -357,3 +612,120 @@ class FeedDashboardModule(DashboardModule):
|
|||
# no date for certain feeds
|
||||
pass
|
||||
self.entries.append(entry)
|
||||
|
||||
|
||||
class DefaultIndexDashboard(Dashboard):
|
||||
"""
|
||||
The default dashboard displayed on the admin index page.
|
||||
To change the default dashboard you'll have to type the following from the
|
||||
commandline in your project root directory::
|
||||
|
||||
python manage.py customdashboard
|
||||
|
||||
And then set the ``ADMIN_TOOLS_INDEX_DASHBOARD`` settings variable to
|
||||
point to your custom index dashboard class.
|
||||
"""
|
||||
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,
|
||||
entries=[
|
||||
{
|
||||
'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'),
|
||||
entries=[
|
||||
{
|
||||
'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):
|
||||
"""
|
||||
The default dashboard displayed on the applications index page.
|
||||
To change the default dashboard you'll have to type the following from the
|
||||
commandline in your project root directory::
|
||||
|
||||
python manage.py customdashboard
|
||||
|
||||
And then set the ``ADMIN_TOOLS_APP_INDEX_DASHBOARD`` settings variable to
|
||||
point to your custom app index dashboard class.
|
||||
"""
|
||||
def render(self, request):
|
||||
|
||||
# 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
|
||||
))
|
||||
|
|
|
@ -17,18 +17,79 @@ 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'),
|
||||
def render(self, request):
|
||||
# append a link list module for "quick links"
|
||||
self.append(LinkListDashboardModule(
|
||||
title=_('Quick links'),
|
||||
layout='inline',
|
||||
draggable=False,
|
||||
deletable=False,
|
||||
collapsible=False,
|
||||
entries=[
|
||||
{
|
||||
'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'),
|
||||
entries=[
|
||||
{
|
||||
'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,
|
||||
},
|
||||
]
|
||||
))
|
||||
|
||||
|
||||
# to activate your app index dashboard you must add the following to your
|
||||
# project's settings.py file:
|
||||
|
@ -38,16 +99,19 @@ class CustomAppIndexDashboard(AppIndexDashboard):
|
|||
"""
|
||||
Document your custom app index dashboard.
|
||||
"""
|
||||
def __init__(self, app_title, models, *args, **kwargs):
|
||||
super(CustomAppIndexDashboard, self).__init__(*args, **kwargs)
|
||||
def render(self, request):
|
||||
# we disable title because its redundant with the model list module
|
||||
self.title = ''
|
||||
|
||||
# append your modules here, example:
|
||||
self.append(AppListDashboardModule(
|
||||
title=_('Modules'),
|
||||
include_list=models,
|
||||
# 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'),
|
||||
limit=5,
|
||||
include_list=models,
|
||||
include_list=self.models,
|
||||
limit=5
|
||||
))
|
||||
|
|
|
@ -4,10 +4,7 @@
|
|||
{% spaceless %}
|
||||
{% for entry in module.entries %}
|
||||
<li class="{% cycle 'odd' 'even' %}">
|
||||
<a{% if entry.external %} class="external-link"{% endif %} href="{{ entry.url }}">{{ entry.title }}</a>
|
||||
{% if entry.description %}
|
||||
<p class="linklist-description">{{ entry.description }}</p>
|
||||
{% endif %}
|
||||
<a{% if entry.external %} class="external-link"{% endif %} href="{{ entry.url }}" {% if entry.description %} title="{{ entry.description }}"{% endif %}>{{ entry.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endspaceless %}
|
||||
|
|
|
@ -24,6 +24,7 @@ def render_dashboard(context, dashboard=None):
|
|||
"""
|
||||
if not dashboard:
|
||||
dashboard = get_dashboard_from_context(context)
|
||||
dashboard.render(context['request'])
|
||||
context.update({
|
||||
'template': dashboard.template,
|
||||
'dashboard': dashboard,
|
||||
|
|
|
@ -9,9 +9,8 @@ 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 import Registry
|
||||
from admin_tools.dashboard.models import *
|
||||
from admin_tools.dashboard.default_dashboard import *
|
||||
|
||||
|
||||
def get_dashboard_from_context(context):
|
||||
|
@ -24,15 +23,18 @@ def get_dashboard_from_context(context):
|
|||
try:
|
||||
app = context['app_list'][0]
|
||||
models = []
|
||||
app_label = app['name']
|
||||
app_label = None
|
||||
app_title = 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
|
||||
split = model.__module__.find(model._meta.app_label)
|
||||
app_label = model.__module__[0:split] + model._meta.app_label
|
||||
app_title = model._meta.app_label.title
|
||||
for m in app['models']:
|
||||
if m['name'] == capfirst(model._meta.verbose_name_plural):
|
||||
mod = '%s.%s' % (model.__module__, model.__name__)
|
||||
models.append(mod)
|
||||
return get_app_index_dashboard(request, app_label, models)
|
||||
return get_app_index_dashboard(request, app_label, app_title, models)
|
||||
except KeyError:
|
||||
return get_app_index_dashboard(request, '', [])
|
||||
|
||||
|
@ -41,47 +43,45 @@ def get_index_dashboard(request):
|
|||
"""
|
||||
Returns the admin dashboard defined by the user or the default one.
|
||||
"""
|
||||
dashboard_cls = getattr(settings, 'ADMIN_TOOLS_INDEX_DASHBOARD', False)
|
||||
if dashboard_cls:
|
||||
try:
|
||||
mod, inst = dashboard_cls.rsplit('.', 1)
|
||||
mod = import_module(mod)
|
||||
return getattr(mod, inst)()
|
||||
except:
|
||||
raise ImproperlyConfigured((
|
||||
'The class pointed by your ADMIN_TOOLS_INDEX_DASHBOARD '
|
||||
'setting variable cannot be imported'
|
||||
))
|
||||
return DefaultIndexDashboard()
|
||||
dashboard_cls = getattr(
|
||||
settings,
|
||||
'ADMIN_TOOLS_INDEX_DASHBOARD',
|
||||
'admin_tools.dashboard.models.DefaultIndexDashboard'
|
||||
)
|
||||
try:
|
||||
mod, inst = dashboard_cls.rsplit('.', 1)
|
||||
mod = import_module(mod)
|
||||
except:
|
||||
raise ImproperlyConfigured((
|
||||
'The class pointed by your ADMIN_TOOLS_INDEX_DASHBOARD '
|
||||
'setting variable cannot be imported'
|
||||
))
|
||||
return getattr(mod, inst)()
|
||||
|
||||
|
||||
def get_app_index_dashboard(request, app_label='', model_list=[]):
|
||||
def get_app_index_dashboard(request, app_label=None, app_title='',
|
||||
model_list=[]):
|
||||
"""
|
||||
Returns the admin dashboard defined by the user or the default one.
|
||||
"""
|
||||
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))
|
||||
# if an app has registered its own dashboard, use it
|
||||
if app_label is not None and app_label in Registry.registry:
|
||||
return Registry.registry[app_label](app_title, model_list)
|
||||
|
||||
# try to discover a general app_index dashboard (with fallback to the
|
||||
# default dashboard)
|
||||
dashboard_cls = getattr(
|
||||
settings,
|
||||
'ADMIN_TOOLS_APP_INDEX_DASHBOARD',
|
||||
'admin_tools.dashboard.models.DefaultAppIndexDashboard'
|
||||
)
|
||||
try:
|
||||
mod = import_module('%s.%s' % (app_label, mod_name))
|
||||
return getattr(mod, mod_class)(app_title, model_list)
|
||||
mod, inst = dashboard_cls.rsplit('.', 1)
|
||||
mod = import_module(mod)
|
||||
except:
|
||||
pass
|
||||
|
||||
# try to discover a general app_index dashboard
|
||||
dashboard_cls = getattr(settings, 'ADMIN_TOOLS_APP_INDEX_DASHBOARD', False)
|
||||
if dashboard_cls:
|
||||
try:
|
||||
mod, inst = dashboard_cls.rsplit('.', 1)
|
||||
mod = import_module(mod)
|
||||
return getattr(mod, inst)(app_title, model_list)
|
||||
except:
|
||||
raise ImproperlyConfigured((
|
||||
'The class pointed by your ADMIN_TOOLS_APP_INDEX_DASHBOARD '
|
||||
'setting variable cannot be imported'
|
||||
))
|
||||
|
||||
# fallback to default dashboard
|
||||
return DefaultAppIndexDashboard(app_title, model_list)
|
||||
raise ImproperlyConfigured((
|
||||
'The class pointed by your ADMIN_TOOLS_APP_INDEX_DASHBOARD '
|
||||
'setting variable cannot be imported'
|
||||
))
|
||||
return getattr(mod, inst)(app_title, model_list)
|
||||
|
|
|
@ -5,26 +5,46 @@ This module contains the base classes for menu and menu items.
|
|||
from django.contrib import admin
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from admin_tools.utils import AppListElementMixin
|
||||
|
||||
|
||||
class Menu(list):
|
||||
"""
|
||||
Base class for menus.
|
||||
The Menu class is a simple python list that takes an optional keyword
|
||||
argument ``template``.
|
||||
The Menu class is a simple python list that has an extra property:
|
||||
|
||||
``template``
|
||||
The template to use to render the menu.
|
||||
Default value: "menu/menu.html".
|
||||
|
||||
>>> m = Menu(template='foo.html')
|
||||
>>> m.template
|
||||
'foo.html'
|
||||
>>> m.append(MenuItem())
|
||||
>>> m.append(MenuItem())
|
||||
>>> len(m)
|
||||
2
|
||||
>>> m.pop().__class__.__name__
|
||||
'MenuItem'
|
||||
>>> len(m)
|
||||
1
|
||||
If you want to customize the look of your menu and it's menu items, you
|
||||
can declare css stylesheets and/or javascript files to include when
|
||||
rendering the menu, for example::
|
||||
|
||||
from admin_tools.menu.models import *
|
||||
|
||||
class MyMenu(Menu):
|
||||
class Media:
|
||||
css = {'screen': '/media/css/mymenu.css'}
|
||||
js = ('/media/js/mymenu.js',)
|
||||
|
||||
Here's an example of a custom menu::
|
||||
|
||||
from admin_tools.menu.models import *
|
||||
|
||||
class MyMenu(Menu):
|
||||
def render(self, request):
|
||||
self.append(MenuItem(title='Home', url=reverse('admin:index')))
|
||||
self.append(AppListMenuItem(title='Applications'))
|
||||
item = MenuItem('Multi level menu item')
|
||||
item.append(MenuItem('Child 1'))
|
||||
item.append(MenuItem('Child 2'))
|
||||
self.append(item)
|
||||
|
||||
Below is a screenshot of the resulting menu:
|
||||
|
||||
.. image:: images/menu_example.png
|
||||
"""
|
||||
|
||||
class Media:
|
||||
|
@ -42,48 +62,56 @@ class Menu(list):
|
|||
super(Menu, self).__init__()
|
||||
self.template = kwargs.get('template', 'menu/menu.html')
|
||||
|
||||
def is_empty(self):
|
||||
def render(self, request):
|
||||
"""
|
||||
Return True if the menu is empty and false otherwise.
|
||||
The ``Menu.render()`` method is called just before the display with a
|
||||
``django.http.HttpRequest`` as unique argument.
|
||||
Override this method to build your menu if you need to access to the
|
||||
request instance.
|
||||
"""
|
||||
return len([i for i in self]) == 0
|
||||
pass
|
||||
|
||||
|
||||
class MenuItem(list):
|
||||
"""
|
||||
Base class for menu items.
|
||||
A menu item is a simple python list that takes some optional keywords
|
||||
arguments. Menu items can be nested.
|
||||
A menu item is a simple python list that has some additional properties:
|
||||
|
||||
``title``
|
||||
String that contains the menu item title, make sure you use the
|
||||
django gettext functions if your application is multilingual.
|
||||
Default value: 'Untitled menu item'.
|
||||
|
||||
``url``
|
||||
String that contains the menu item URL.
|
||||
Default value: '#'.
|
||||
|
||||
``css_classes``
|
||||
A list of css classes to be added to the menu item ``li`` class
|
||||
attribute. Default value: None.
|
||||
|
||||
``accesskey``
|
||||
The menu item accesskey. Default value: None.
|
||||
|
||||
``description``
|
||||
An optional string that will be used as the ``title`` attribute of
|
||||
the menu-item ``a`` tag. Default value: None.
|
||||
|
||||
``template``
|
||||
The template to use to render the menu item.
|
||||
Default value: 'menu/item.html'.
|
||||
|
||||
Menu items can be nested so for example you can do the following::
|
||||
|
||||
from admin_tools.menu.models import *
|
||||
|
||||
mymenu = Menu()
|
||||
item = MenuItem(title='Foo')
|
||||
item.append(MenuItem(title='Bar'))
|
||||
mymenu.append(item)
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
MenuItem module constructor, keywords arguments (all are optional):
|
||||
|
||||
``title``
|
||||
String that contains the menu item title, make sure you use the
|
||||
django gettext functions if your application is multilingual.
|
||||
Default value: 'Untitled menu item'.
|
||||
|
||||
``url``
|
||||
String that contains the menu item URL.
|
||||
Default value: '#'.
|
||||
|
||||
``css_classes``
|
||||
A list of css classes to be added to the menu item ``li`` class
|
||||
attribute. Default value: None.
|
||||
|
||||
``accesskey``
|
||||
The menu item accesskey. Default value: None.
|
||||
|
||||
``description``
|
||||
An optional string that will be used as the ``title`` attribute of
|
||||
the menu-item ``a`` tag. Default value: None.
|
||||
|
||||
``template``
|
||||
The template to use to render the menu item.
|
||||
Default value: 'menu/item.html'.
|
||||
"""
|
||||
super(MenuItem, self).__init__()
|
||||
self.title = kwargs.get('title', 'Untitled menu item')
|
||||
self.url = kwargs.get('url', '#')
|
||||
|
@ -93,12 +121,66 @@ class MenuItem(list):
|
|||
self.template = kwargs.get('template', 'menu/item.html')
|
||||
|
||||
def render(self, request):
|
||||
"""
|
||||
The ``MenuItem.render()`` is called just before the display with a
|
||||
``django.http.HttpRequest`` as unique argument.
|
||||
You can use it to build your item when you need to access the request
|
||||
instance, for example::
|
||||
|
||||
from admin_tools.menu.models import *
|
||||
|
||||
class MyMenuItem(MenuItem):
|
||||
def render(self, request):
|
||||
if request.user.username == 'foo':
|
||||
self.title = 'Foo'
|
||||
else:
|
||||
self.title = 'Bar'
|
||||
|
||||
mymenu = Menu()
|
||||
mymenu.append(MyMenuItem())
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class AppListMenuItem(MenuItem, AppListElementMixin):
|
||||
"""
|
||||
Class that represents a menu item that lists installed apps.
|
||||
A menu item that lists installed apps an their models.
|
||||
As well as the ``MenuItem`` properties, the ``AppListMenuItem`` has two
|
||||
extra properties:
|
||||
|
||||
``exclude_list``
|
||||
A list of apps to exclude, if an app name (e.g. "django.contrib.auth"
|
||||
starts with an element of this list (e.g. "django.contrib") it won't
|
||||
appear in the menu item.
|
||||
|
||||
``include_list``
|
||||
A list of apps to include, only apps whose name (e.g.
|
||||
"django.contrib.auth") starts with one of the strings (e.g.
|
||||
"django.contrib") in the list will appear in the menu item.
|
||||
|
||||
If no include/exclude list is provided, **all apps** are shown.
|
||||
|
||||
Here's a small example of building an app list menu item::
|
||||
|
||||
from admin_tools.menu.models import *
|
||||
|
||||
mymenu = Menu()
|
||||
|
||||
# will list all apps except the django.contrib ones
|
||||
mymenu.append(AppListMenuItem(
|
||||
title='Applications',
|
||||
exclude_list=('django.contrib',)
|
||||
))
|
||||
|
||||
The screenshot of what this code produces:
|
||||
|
||||
.. image:: images/applist_menu_item.png
|
||||
|
||||
.. note::
|
||||
|
||||
Note that this module takes into account user permissions, for
|
||||
example, if a user has no rights to change or add a ``Group``, then
|
||||
the django.contrib.auth.Group model child item will not be displayed.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -134,3 +216,29 @@ class AppListMenuItem(MenuItem, AppListElementMixin):
|
|||
for model_dict in apps[app]['models']:
|
||||
item.append(MenuItem(**model_dict))
|
||||
self.append(item)
|
||||
|
||||
|
||||
class DefaultMenu(Menu):
|
||||
"""
|
||||
The default menu displayed by default by django-admin-tools.
|
||||
To change the default menu you'll have to type the following from the
|
||||
commandline in your project root directory::
|
||||
|
||||
python manage.py custommenu
|
||||
|
||||
And then set the ``ADMIN_TOOLS_MENU`` settings variable to point to your
|
||||
custom menu class.
|
||||
"""
|
||||
def render(self, request):
|
||||
self.append(MenuItem(
|
||||
title=_('Dashboard'),
|
||||
url=reverse('admin:index')
|
||||
))
|
||||
self.append(AppListMenuItem(
|
||||
title=_('Applications'),
|
||||
exclude_list=('django.contrib',),
|
||||
))
|
||||
self.append(AppListMenuItem(
|
||||
title=_('Administration'),
|
||||
include_list=('django.contrib',),
|
||||
))
|
||||
|
|
|
@ -11,7 +11,7 @@ var hover_ie6 = function() {
|
|||
window.onload = hover_ie6;
|
||||
</script>
|
||||
<![endif]-->
|
||||
{% if not menu.is_empty %}
|
||||
{% if menu %}
|
||||
<ul id="navigation-menu">
|
||||
{% for item in menu %}{% render_menu_item item forloop.counter %}{% endfor %}
|
||||
</div>
|
||||
|
|
|
@ -17,15 +17,16 @@ class CustomMenu(Menu):
|
|||
"""
|
||||
Returns the admin menu defined by the user or the default one.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CustomMenu, self).__init__(*args, **kwargs)
|
||||
|
||||
# append your menu items here, for example:
|
||||
def render(self, request):
|
||||
self.append(MenuItem(
|
||||
title=_('Home'),
|
||||
title=_('Dashboard'),
|
||||
url=reverse('admin:index')
|
||||
))
|
||||
self.append(MenuItem(
|
||||
title=_('Some link'),
|
||||
url='http://example.com'
|
||||
self.append(AppListMenuItem(
|
||||
title=_('Applications'),
|
||||
exclude_list=('django.contrib',),
|
||||
))
|
||||
self.append(AppListMenuItem(
|
||||
title=_('Administration'),
|
||||
include_list=('django.contrib',),
|
||||
))
|
||||
|
|
|
@ -23,6 +23,7 @@ def render_menu(context, menu=None):
|
|||
"""
|
||||
if menu is None:
|
||||
menu = get_admin_menu(context['request'])
|
||||
menu.render(context['request'])
|
||||
context.update({
|
||||
'template': menu.template,
|
||||
'menu': menu,
|
||||
|
|
|
@ -14,29 +14,17 @@ def get_admin_menu(request):
|
|||
"""
|
||||
Returns the admin menu defined by the user or the default one.
|
||||
"""
|
||||
menu_cls = getattr(settings, 'ADMIN_TOOLS_MENU', False)
|
||||
if menu_cls:
|
||||
try:
|
||||
mod, inst = menu_cls.rsplit('.', 1)
|
||||
mod = import_module(mod)
|
||||
return getattr(mod, inst)()
|
||||
except:
|
||||
raise ImproperlyConfigured((
|
||||
'The class pointed by your ADMIN_TOOLS_MENU setting variable '
|
||||
'cannot be imported'
|
||||
))
|
||||
|
||||
admin_menu = Menu()
|
||||
admin_menu.append(MenuItem(
|
||||
title=_('Dashboard'),
|
||||
url=reverse('admin:index')
|
||||
))
|
||||
admin_menu.append(AppListMenuItem(
|
||||
title=_('Applications'),
|
||||
exclude_list=('django.contrib',),
|
||||
))
|
||||
admin_menu.append(AppListMenuItem(
|
||||
title=_('Administration'),
|
||||
include_list=('django.contrib',),
|
||||
))
|
||||
return admin_menu
|
||||
menu_cls = getattr(
|
||||
settings,
|
||||
'ADMIN_TOOLS_MENU',
|
||||
'admin_tools.menu.models.DefaultMenu'
|
||||
)
|
||||
try:
|
||||
mod, inst = menu_cls.rsplit('.', 1)
|
||||
mod = import_module(mod)
|
||||
except:
|
||||
raise ImproperlyConfigured((
|
||||
'The class pointed by your ADMIN_TOOLS_MENU setting variable '
|
||||
'cannot be imported'
|
||||
))
|
||||
return getattr(mod, inst)()
|
||||
|
|
|
@ -16,7 +16,9 @@ import sys, os
|
|||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.append(os.path.abspath('.'))
|
||||
sys.path.append(os.path.abspath('..'))
|
||||
# required for autodoc
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'django.conf.global_settings'
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
.. _configuration:
|
||||
|
||||
Configuring django-admin-tools
|
||||
==============================
|
||||
|
||||
Basic configuration
|
||||
-------------------
|
||||
|
||||
Once installed, you can add django-admin-tools to any Django-based
|
||||
project you're developing.
|
||||
|
||||
django-admin-tools is composed of several modules:
|
||||
|
||||
* admin_tools.theming: an app that makes it easy to customize the look
|
||||
and feel of the admin interface;
|
||||
|
||||
* admin_tools.menu: a customizable navigation menu that sits on top of
|
||||
every django administration index page;
|
||||
|
||||
* admin_tools.dashboard: a customizable dashboard that replaces the django
|
||||
administration index page.
|
||||
|
||||
Required settings
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
First make sure you have the following template context processors
|
||||
installed::
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
'django.core.context_processors.auth',
|
||||
'django.core.context_processors.request',
|
||||
)
|
||||
|
||||
Then, add the django-admin-tools modules to the ``INSTALLED_APPS`` like
|
||||
this::
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'admin_tools.theming',
|
||||
'admin_tools.menu',
|
||||
'admin_tools.dashboard',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.admin'
|
||||
# ...other installed applications...
|
||||
)
|
||||
|
||||
.. note::
|
||||
it is very important that you put the admin_tools modules **before**
|
||||
the ``django.contrib.admin module``, because django-admin-tools
|
||||
overrides the default django admin templates, and this will not work
|
||||
otherwise.
|
||||
|
||||
django-admin-tools is modular, so if you want to disable a particular
|
||||
module, just remove or comment it in your ``INSTALLED_APPS``.
|
||||
For example, if you just want to use the dashboard::
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'admin_tools.dashboard',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.admin'
|
||||
# ...other installed applications...
|
||||
)
|
||||
|
||||
|
||||
Setting up the django-admin-tools media files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To do this you have two options:
|
||||
|
||||
* create a symbolic link to the django-admin-tools media files to your
|
||||
``MEDIA_ROOT`` directory, for example::
|
||||
|
||||
ln -s /usr/local/lib/python2.6/dist-packages/admin_tools/media/admin_tools /path/to/yourproject/media/
|
||||
|
||||
* copy the django-admin-tools media files to your ``MEDIA_ROOT`` directory,
|
||||
for example::
|
||||
|
||||
cp -r /usr/local/lib/python2.6/dist-packages/admin_tools/media/admin_tools /path/to/yourproject/media/
|
||||
|
||||
|
||||
Available settings variables
|
||||
----------------------------
|
||||
|
||||
``ADMIN_TOOLS_MENU``
|
||||
The path to your custom menu class, for example
|
||||
"yourproject.menu.CustomMenu".
|
||||
|
||||
``ADMIN_TOOLS_INDEX_DASHBOARD``
|
||||
The path to your custom index dashboard, for example
|
||||
"yourproject.dashboard.CustomIndexDashboard".
|
||||
|
||||
``ADMIN_TOOLS_APP_INDEX_DASHBOARD``
|
||||
The path to your custom app index dashboard, for example
|
||||
"yourproject.dashboard.CustomAppIndexDashboard".
|
||||
|
||||
``ADMIN_TOOLS_THEMING_CSS``
|
||||
The path to your theming css stylesheet, relative to your MEDIA_URL,
|
||||
for example::
|
||||
|
||||
ADMIN_TOOLS_THEMING_CSS = 'css/theming.css'
|
||||
|
|
@ -6,21 +6,110 @@ Customization of the django-admin-tools modules
|
|||
Introduction
|
||||
------------
|
||||
|
||||
todo: write docs for "Customizing introduction"
|
||||
django-admin-tools is very easy to customize, you can override the
|
||||
admin menu, the index dashboard and the app index dashboard.
|
||||
|
||||
For this django-admin-tools provides two management commands:
|
||||
* ``custommenu``
|
||||
* ``customdashboard``
|
||||
|
||||
|
||||
Customizing the navigation menu
|
||||
-------------------------------
|
||||
|
||||
todo: write docs for "Customizing the navigation menu"
|
||||
To customize the admin menu, the first step is to do the following::
|
||||
|
||||
python manage.py custommenu
|
||||
|
||||
This will create a file named ``menu.py`` in your project directory.
|
||||
If for some reason you want another file name, you can do::
|
||||
|
||||
python manage.py custommenu somefile.py
|
||||
|
||||
The created file contains a class that is a copy of the default menu,
|
||||
it is named ``CustomMenu``, you can rename it if you want but if you do
|
||||
so, make sure you put the correct class name in your ADMIN_TOOLS_MENU
|
||||
settings variable.
|
||||
|
||||
.. note::
|
||||
You could have done the above by hand, without using the
|
||||
``custommenu`` management command, but it's simpler with it.
|
||||
|
||||
|
||||
Now you need to tell django-admin-tools to use your custom menu instead
|
||||
of the default one, open your settings.py file and add the following::
|
||||
|
||||
ADMIN_TOOLS_MENU = 'yourproject.menu.CustomMenu'
|
||||
|
||||
Obviously, you need to change "yourproject" to the real project name,
|
||||
if you have chosen a different file name or if you renamed the menu
|
||||
class, you'll also need to change the above string to reflect your
|
||||
modifications.
|
||||
|
||||
At this point the menu displayed in the admin is your custom menu, now
|
||||
you can read :ref:`the menu and menu items API documentation <menu>`
|
||||
to learn how to create your custom menu.
|
||||
|
||||
|
||||
Customizing the dashboards
|
||||
--------------------------
|
||||
|
||||
todo: write docs for "Customizing the dashboards"
|
||||
To customize the index and app index dashboards, the first step is to do
|
||||
the following::
|
||||
|
||||
python manage.py customdashboard
|
||||
|
||||
This will create a file named ``dashboard.py`` in your project directory.
|
||||
If for some reason you want another file name, you can do::
|
||||
|
||||
python manage.py customdashboard somefile.py
|
||||
|
||||
The created file contains two classes:
|
||||
* The ``CustomIndexDashboard`` class that corresponds to the admin
|
||||
index page dashboard;
|
||||
* The ``CustomAppIndexDashboard`` class that corresponds to the
|
||||
index page of each installed application.
|
||||
|
||||
You can rename theses classes if you want but if you do so, make sure
|
||||
adjust the ``ADMIN_TOOLS_INDEX_DASHBOARD`` and
|
||||
``ADMIN_TOOLS_APP_INDEX_DASHBOARD`` settings variables to match your
|
||||
class names.
|
||||
|
||||
.. note::
|
||||
You could have done the above by hand, without using the
|
||||
``customdashboard`` management command, but it's simpler with it.
|
||||
|
||||
|
||||
Customizing the look and feel
|
||||
-----------------------------
|
||||
Now you need to tell django-admin-tools to use your custom dashboard(s).
|
||||
Open your settings.py file and add the following::
|
||||
|
||||
todo: write docs for "Customizing the look and feel"
|
||||
ADMIN_TOOLS_INDEX_DASHBOARD = 'yourproject.dashboard.CustomIndexDashboard'
|
||||
ADMIN_TOOLS_APP_INDEX_DASHBOARD = 'yourproject.dashboard.CustomAppIndexDashboard'
|
||||
|
||||
If you only want a custom index dashboard, you would just need the first
|
||||
line. Obviously, you need to change "yourproject" to the real project name,
|
||||
if you have chosen a different file name or if you renamed the dashboard
|
||||
classes, you'll also need to change the above string to reflect your
|
||||
modifications.
|
||||
|
||||
At this point the dashboards displayed in the index and the app index
|
||||
should be your custom dashboards, now you can read
|
||||
:ref:`the dashboard and dashboard modules API documentation <dashboard>`
|
||||
to learn how to create your custom dashboard.
|
||||
|
||||
|
||||
Customizing the theme
|
||||
---------------------
|
||||
|
||||
.. warning::
|
||||
The theming support is still very basic and I'm still not sure it's
|
||||
a good idea, so do not rely to much on it for the moment.
|
||||
|
||||
This is very simple, just configure the ``ADMIN_TOOLS_THEMING_CSS`` to
|
||||
point to your custom css file, for example::
|
||||
|
||||
ADMIN_TOOLS_THEMING_CSS = 'css/theming.css'
|
||||
|
||||
A good start is to copy the
|
||||
``admin_tools/media/admin_tools/css/theming.css`` to your custom file and
|
||||
to modify it to suits your needs.
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
.. _dashboard:
|
||||
|
||||
The django-admin-tools dashboard and dashboard modules API
|
||||
==========================================================
|
||||
|
||||
This section describe the API of the django-admin-tools dashboard and
|
||||
dashboard modules.
|
||||
Make sure you read this before creating your custom dashboard and
|
||||
custom modules.
|
||||
|
||||
The ``Dashboard`` class
|
||||
-----------------------
|
||||
|
||||
.. autoclass:: admin_tools.dashboard.models.Dashboard
|
||||
:members:
|
||||
|
||||
The ``AppIndexDashboard`` class
|
||||
-------------------------------
|
||||
|
||||
.. autoclass:: admin_tools.dashboard.models.AppIndexDashboard
|
||||
:members:
|
||||
|
||||
The ``DashboardModule`` class
|
||||
-----------------------------
|
||||
|
||||
.. autoclass:: admin_tools.dashboard.models.DashboardModule
|
||||
:members:
|
||||
|
||||
The ``LinkListDashboardModule`` class
|
||||
-------------------------------------
|
||||
|
||||
.. autoclass:: admin_tools.dashboard.models.LinkListDashboardModule
|
||||
:members:
|
||||
|
||||
The ``AppListDashboardModule`` class
|
||||
------------------------------------
|
||||
|
||||
.. autoclass:: admin_tools.dashboard.models.AppListDashboardModule
|
||||
:members:
|
||||
|
||||
The ``RecentActionsDashboardModule`` class
|
||||
------------------------------------------
|
||||
|
||||
.. autoclass:: admin_tools.dashboard.models.RecentActionsDashboardModule
|
||||
:members:
|
||||
|
||||
The ``FeedDashboardModule`` class
|
||||
---------------------------------
|
||||
|
||||
.. autoclass:: admin_tools.dashboard.models.FeedDashboardModule
|
||||
:members:
|
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 21 KiB |
|
@ -8,7 +8,16 @@ Welcome to django-admin-tools's documentation!
|
|||
|
||||
This documentation covers the latest release of django-admin-tools, a
|
||||
collection of extensions and tools for the
|
||||
`Django <http://www.djangoproject.com>`_ administration interface.
|
||||
`Django <http://www.djangoproject.com>`_ administration interface,
|
||||
django-admin-tools includes:
|
||||
|
||||
* a full featured and customizable dashboard (for the admin index page
|
||||
and the admin applications index pages),
|
||||
* a customizable menu bar,
|
||||
* tools to make admin theming easier.
|
||||
|
||||
It was originally developed for django-cms, and then extracted to this
|
||||
pluggable app.
|
||||
|
||||
To get up and running quickly, consult the :ref:`quick-start guide
|
||||
<quickstart>`, which describes all the necessary steps to install
|
||||
|
@ -23,4 +32,8 @@ Contents:
|
|||
|
||||
quickstart
|
||||
installation
|
||||
configuration
|
||||
customization
|
||||
menu
|
||||
dashboard
|
||||
integration
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
.. _integration:
|
||||
|
||||
Integration with third party applications
|
||||
=========================================
|
||||
|
||||
todo: write doc for "Integration with third party applications" section.
|
|
@ -0,0 +1,25 @@
|
|||
.. _menu:
|
||||
|
||||
The django-admin-tools menu and menu items API
|
||||
==============================================
|
||||
|
||||
This section describe the API of the django-admin-tools menu and menu items.
|
||||
Make sure you read this before creating your custom menu.
|
||||
|
||||
The ``Menu`` class
|
||||
------------------
|
||||
|
||||
.. autoclass:: admin_tools.menu.models.Menu
|
||||
:members:
|
||||
|
||||
The ``MenuItem`` class
|
||||
----------------------
|
||||
|
||||
.. autoclass:: admin_tools.menu.models.MenuItem
|
||||
:members:
|
||||
|
||||
The ``AppListMenuItem`` class
|
||||
-----------------------------
|
||||
|
||||
.. autoclass:: admin_tools.menu.models.AppListMenuItem
|
||||
:members:
|
|
@ -34,19 +34,8 @@ Using ``pip``, type::
|
|||
Basic configuration
|
||||
-------------------
|
||||
|
||||
Once installed, you can add django-admin-tools to any Django-based
|
||||
project you're developing.
|
||||
|
||||
django-admin-tools is composed of several modules:
|
||||
|
||||
* admin_tools.theming: an app that makes it easy to customize the look
|
||||
and feel of the admin interface;
|
||||
|
||||
* admin_tools.menu: a customizable navigation menu that sits on top of
|
||||
every django administration index page;
|
||||
|
||||
* admin_tools.dashboard: a customizable dashboard that replaces the django
|
||||
administration index page.
|
||||
For a more detailed guide on how to configure django-admin-tools, please
|
||||
consult :ref:`the configuration section <configuration>`.
|
||||
|
||||
Required settings
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
@ -72,7 +61,7 @@ this::
|
|||
# ...other installed applications...
|
||||
)
|
||||
|
||||
.. note::
|
||||
.. important::
|
||||
it is very important that you put the admin_tools modules **before**
|
||||
the ``django.contrib.admin module``, because django-admin-tools
|
||||
overrides the default django admin templates, and this will not work
|
||||
|
@ -80,16 +69,6 @@ this::
|
|||
|
||||
django-admin-tools is modular, so if you want to disable a particular
|
||||
module, just remove or comment it in your ``INSTALLED_APPS``.
|
||||
For example, if you just want to use the dashboard::
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'admin_tools.dashboard',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.admin'
|
||||
# ...other installed applications...
|
||||
)
|
||||
|
||||
|
||||
Setting up the django-admin-tools media files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|