| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 | import jsonfrom django import formsfrom django.contrib.admin.models import LogEntryfrom django.db.models import Qfrom django.template.loader import render_to_stringfrom django.utils.translation import ugettext_lazy as _from jet.utils import get_app_list, LazyDateTimeEncoderimport datetimeclass DashboardModule(object):    """    Base dashboard module class. All dashboard modules (widgets) should inherit it.    """    #: Path to widget's template. There is no need to extend such templates from any base templates.    template = 'jet.dashboard/module.html'    enabled = True    draggable = True    collapsible = True    deletable = True    show_title = True    #: Default widget title that will be displayed for widget in the dashboard. User can change it later    #: for every widget.    title = ''    title_url = None    css_classes = None    #: HTML content that will be displayed before widget content.    pre_content = None    #: HTML content that will be displayed after widget content.    post_content = None    children = None    #: A ``django.forms.Form`` class which may contain custom widget settings. Not required.    settings_form = None    #: A ``django.forms.Form`` class which may contain custom widget child settings, if it has any. Not required.    child_form = None    child_name = None    child_name_plural = None    settings = None    column = None    order = None    #: A boolean field which specify if widget should be rendered on dashboard page load or fetched    #: later via AJAX.    ajax_load = False    #: A boolean field which makes widget ui color contrast.    contrast = False    #: Optional style attributes which will be applied to widget content container.    style = False    class Media:        css = ()        js = ()    def __init__(self, title=None, model=None, context=None, **kwargs):        if title is not None:            self.title = title        self.model = model        self.context = context or {}        for key in kwargs:            if hasattr(self.__class__, key):                setattr(self, key, kwargs[key])        self.children = self.children or []        if self.model:            self.load_from_model()    def fullname(self):        return self.__module__ + "." + self.__class__.__name__    def load_settings(self, settings):        pass    def load_children(self, children):        self.children = children    def store_children(self):        return False    def settings_dict(self):        pass    def dump_settings(self, settings=None):        settings = settings or self.settings_dict()        if settings:            return json.dumps(settings, cls=LazyDateTimeEncoder)        else:            return ''    def dump_children(self):        if self.store_children():            return json.dumps(self.children, cls=LazyDateTimeEncoder)        else:            return ''    def load_from_model(self):        self.title = self.model.title        if self.model.settings:            try:                self.settings = json.loads(self.model.settings)                self.load_settings(self.settings)            except ValueError:                pass        if self.store_children() and self.model.children:            try:                children = json.loads(self.model.children)                self.load_children(children)            except ValueError:                pass    def init_with_context(self, context):        pass    def get_context_data(self):        context = self.context        context.update({            'module': self        })        return context    def render(self):        self.init_with_context(self.context)        return render_to_string(self.template, self.get_context_data())class LinkListItemForm(forms.Form):    url = forms.CharField(label=_('URL'))    title = forms.CharField(label=_('Title'))    external = forms.BooleanField(label=_('External link'), required=False)class LinkListSettingsForm(forms.Form):    layout = forms.ChoiceField(label=_('Layout'), choices=(('stacked', _('Stacked')), ('inline', _('Inline'))))class LinkList(DashboardModule):    """    List of links widget.    Usage example:    .. code-block:: python        from django.utils.translation import ugettext_lazy as _        from jet.dashboard import modules        from jet.dashboard.dashboard import Dashboard, AppIndexDashboard        class CustomIndexDashboard(Dashboard):            columns = 3            def init_with_context(self, context):                self.available_children.append(modules.LinkList)                self.children.append(modules.LinkList(                    _('Support'),                    children=[                        {                            '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,                        },                    ],                    column=0,                    order=0                ))    """    title = _('Links')    template = 'jet.dashboard/modules/link_list.html'    #: Specify widget layout.    #: Allowed values ``stacked`` and ``inline``.    layout = 'stacked'    #: Links are contained in ``children`` attribute which you can pass as constructor parameter    #: to make your own preinstalled link lists.    #:    #: ``children`` is an array of dictinaries::    #:    #:     [    #:          {    #:              'title': _('Django documentation'),    #:              'url': 'http://docs.djangoproject.com/',    #:              'external': True,    #:          },    #:          ...    #:     ]    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 linkclass AppList(DashboardModule):    """    Shows applications and containing models links. For each model "created" and "change" links are displayed.    Usage example:    .. code-block:: python        from django.utils.translation import ugettext_lazy as _        from jet.dashboard import modules        from jet.dashboard.dashboard import Dashboard, AppIndexDashboard        class CustomIndexDashboard(Dashboard):            columns = 3            def init_with_context(self, context):                self.children.append(modules.AppList(                    _('Applications'),                    exclude=('auth.*',),                    column=0,                    order=0                ))    """    title = _('Applications')    template = 'jet.dashboard/modules/app_list.html'    #: Specify models which should be displayed. ``models`` is an array of string formatted as ``app_label.model``.    #: Also its possible to specify all application models with * sign (e.g. ``auth.*``).    models = None    #: Specify models which should NOT be displayed. ``exclude`` is an array of string formatted as ``app_label.model``.    #: Also its possible to specify all application models with * sign (e.g. ``auth.*``).    exclude = None    hide_empty = True    def settings_dict(self):        return {            'models': self.models,            'exclude': self.exclude        }    def load_settings(self, settings):        self.models = settings.get('models')        self.exclude = settings.get('exclude')    def init_with_context(self, context):        app_list = get_app_list(context)        app_to_remove = []        for app in app_list:            app['models'] = filter(                lambda model: self.models is None or model['object_name'] in self.models or app.get('app_label', app.get('name')) + '.*' in self.models,                app['models']            )            app['models'] = filter(                lambda model: self.exclude is None or model['object_name'] not in self.exclude and app.get('app_label', app.get('name')) + '.*' not in self.exclude,                app['models']            )            app['models'] = list(app['models'])            if self.hide_empty and len(list(app['models'])) == 0:                app_to_remove.append(app)        for app in app_to_remove:            app_list.remove(app)        self.children = app_listclass ModelList(DashboardModule):    """    Shows models links. For each model "created" and "change" links are displayed.    Usage example:    .. code-block:: python        from django.utils.translation import ugettext_lazy as _        from jet.dashboard import modules        from jet.dashboard.dashboard import Dashboard, AppIndexDashboard        class CustomIndexDashboard(Dashboard):            columns = 3            def init_with_context(self, context):                self.children.append(modules.ModelList(                    _('Models'),                    exclude=('auth.*',),                    column=0,                    order=0                ))    """    title = _('Models')    template = 'jet.dashboard/modules/model_list.html'    #: Specify models which should be displayed. ``models`` is an array of string formatted as ``app_label.model``.    #: Also its possible to specify all application models with * sign (e.g. ``auth.*``).    models = None    #: Specify models which should NOT be displayed. ``exclude`` is an array of string formatted as ``app_label.model``.    #: Also its possible to specify all application models with * sign (e.g. ``auth.*``).    exclude = None    hide_empty = True    def settings_dict(self):        return {            'models': self.models,            'exclude': self.exclude        }    def load_settings(self, settings):        self.models = settings.get('models')        self.exclude = settings.get('exclude')    def init_with_context(self, context):        app_list = get_app_list(context)        models = []        for app in app_list:            app['models'] = filter(                lambda model: self.models is None or model['object_name'] in self.models or app.get('app_label', app.get('name')) + '.*' in self.models,                app['models']            )            app['models'] = filter(                lambda model: self.exclude is None or model['object_name'] not in self.exclude and app.get('app_label', app.get('name')) + '.*' not in self.exclude,                app['models']            )            app['models'] = list(app['models'])            models.extend(app['models'])        self.children = modelsclass RecentActionsSettingsForm(forms.Form):    limit = forms.IntegerField(label=_('Items limit'), min_value=1)class RecentActions(DashboardModule):    """    Display list of most recent admin actions with following information:    entity name, type of action, author, date    Usage example:    .. code-block:: python        from django.utils.translation import ugettext_lazy as _        from jet.dashboard import modules        from jet.dashboard.dashboard import Dashboard, AppIndexDashboard        class CustomIndexDashboard(Dashboard):            columns = 3            def init_with_context(self, context):                self.children.append(modules.RecentActions(                    _('Recent Actions'),                    10,                    column=0,                    order=0                ))    """    title = _('Recent Actions')    template = 'jet.dashboard/modules/recent_actions.html'    #: Number if entries to be shown (may be changed by each user personally).    limit = 10    #: Specify actions of which models should be displayed. ``include_list`` is an array of string    #: formatted as ``app_label.model``. Also its possible to specify all application models    #: with * sign (e.g. ``auth.*``).    include_list = None    #: Specify actions of which models should NOT be displayed. ``exclude_list`` is an array of string    #: formatted as ``app_label.model``. Also its possible to specify all application models    #: with * sign (e.g. ``auth.*``).    exclude_list = None    settings_form = RecentActionsSettingsForm    user = None    def __init__(self, title=None, limit=10, **kwargs):        kwargs.update({'limit': limit})        super(RecentActions, self).__init__(title, **kwargs)    def settings_dict(self):        return {            'limit': self.limit,            'include_list': self.include_list,            'exclude_list': self.exclude_list,            'user': self.user        }    def load_settings(self, settings):        self.limit = settings.get('limit', self.limit)        self.include_list = settings.get('include_list')        self.exclude_list = settings.get('exclude_list')        self.user = settings.get('user', None)    def init_with_context(self, context):        def get_qset(list):            qset = None            for contenttype in list:                try:                    app_label, model = contenttype.split('.')                    if model == '*':                        current_qset = Q(                            content_type__app_label=app_label                        )                    else:                        current_qset = Q(                            content_type__app_label=app_label,                            content_type__model=model                        )                except:                    raise ValueError('Invalid contenttype: "%s"' % contenttype)                if qset is None:                    qset = current_qset                else:                    qset = qset | current_qset            return qset        qs = LogEntry.objects        if self.user:            qs = qs.filter(                user__pk=int(self.user)            )        if self.include_list:            qs = qs.filter(get_qset(self.include_list))        if self.exclude_list:            qs = qs.exclude(get_qset(self.exclude_list))        self.children = qs.select_related('content_type', 'user')[:int(self.limit)]class FeedSettingsForm(forms.Form):    limit = forms.IntegerField(label=_('Items limit'), min_value=1)    feed_url = forms.URLField(label=_('Feed URL'))class Feed(DashboardModule):    """    Display RSS Feed entries with following information:    entry title, date and link to the full version    Usage example:    .. code-block:: python        from django.utils.translation import ugettext_lazy as _        from jet.dashboard import modules        from jet.dashboard.dashboard import Dashboard, AppIndexDashboard        class CustomIndexDashboard(Dashboard):            columns = 3            def init_with_context(self, context):                self.children.append(modules.Feed(                    _('Latest Django News'),                    feed_url='http://www.djangoproject.com/rss/weblog/',                    limit=5,                    column=0,                    order=0                ))    """    title = _('RSS Feed')    template = 'jet.dashboard/modules/feed.html'    #: URL of the RSS feed (may be changed by each user personally).    feed_url = None    #: Number if entries to be shown (may be changed by each user personally).    limit = None    settings_form = FeedSettingsForm    ajax_load = True    def __init__(self, title=None, feed_url=None, limit=None, **kwargs):        kwargs.update({'feed_url': feed_url, 'limit': limit})        super(Feed, self).__init__(title, **kwargs)    def settings_dict(self):        return {            'feed_url': self.feed_url,            'limit': self.limit        }    def load_settings(self, settings):        self.feed_url = settings.get('feed_url')        self.limit = settings.get('limit')    def init_with_context(self, context):        if self.feed_url is not None:            try:                import feedparser                feed = feedparser.parse(self.feed_url)                if self.limit is not None:                    entries = feed['entries'][:self.limit]                else:                    entries = feed['entries']                for entry in entries:                    try:                        entry.date = datetime.date(*entry.published_parsed[0:3])                    except:                        pass                    self.children.append(entry)            except ImportError:                self.children.append({                    'title': _('You must install the FeedParser python module'),                    'warning': True,                })        else:            self.children.append({                'title': _('You must provide a valid feed URL'),                'warning': True,            })
 |