跳转到主要内容

可自定义、模块化Django仪表盘应用框架。

项目描述

django-dash (后来命名为Dash) 是一个可自定义、模块化的Django仪表盘应用框架。

Dash 允许用户创建自己的自定义仪表盘。支持主题化(在Dash中,主题被称为布局)和多个工作区。Dash附带丰富的Pythonic API,允许开发人员创建新的Dash插件,以及修改内置的插件。

为了更清晰地关联,想想平板电脑上的Android(快捷方式、小工具和应用程序)或平板电脑或桌面上的Windows 8。

Dash 继承了所有这些概念,并使得在Django应用程序中实现仪表盘系统变得轻而易举。

PyPI Version Supported Python versions Build Status Documentation Status GPL-2.0-only OR LGPL-2.1-or-later Coverage

先决条件

  • Django 2.2、3.0和3.1

  • Python 3.6、3.7、3.8和3.9。

关键概念

  • 每个布局(主题)都由占位符组成。每个插件小部件都有其特定的HTML/JavaScript/CSS。

  • 可能已实现并安装了多个主题。默认布局是系统范围内的选择,但每个用户(如果具有适当的权限)都可以在所有工作空间中选择他喜欢的布局,甚至可以在每个工作空间中设置不同的布局。

  • 占位符是一个空间,插件小部件被放置在这里。

  • 占位符由单元格组成的矩形。每个占位符都有其自定义的行数和列数。

  • 工作空间只是另一个命名的仪表板。用户在导航中切换工作空间。工作空间的数量是无限的。

  • 插件是一个(Django)微应用。大部分重负载工作应该在插件中完成。插件可以有自己的视图、urls等。渲染是通过使用插件小部件来完成的。

  • 插件小部件主要负责渲染插件数据。每个插件小部件都有自己的特定HTML/JavaScript/CSS。单个插件小部件为三元组(布局、占位符、插件)注册。

  • 公开仪表板(作为contrib应用实现,使其成为可选功能)允许用户使他们的工作空间公开。如果用户选择使他们的仪表板公开,则默认工作空间变为公开。至于非默认工作空间,用户仍然可以使它们每个都是私有的或公开的。

主要功能

  • 可定制的布局(也称为主题)。

  • 多个工作空间。

  • 可调整插件访问权限。

  • 公开仪表板(作为一个contrib应用)。

  • 可克隆的工作空间。可以将整个工作空间(包括所有插件)克隆到另一个工作空间中。

  • 插件小部件的复制/粘贴功能。

常见问题解答

  • 问题:Dash是否可以与(选择适用的:D3、Polychart2或其他用于制作图表的库)一起工作。

    答案:是的。查看以下样本插件的源代码

一些截图

查看文档以获取一些屏幕截图

演示

实时演示

查看Heroku上的实时演示应用

凭证

  • 用户名:test_user

  • 密码:test_user

查看test_demo_user的公开仪表板,以了解它可能成为的样子。

在本地运行演示

为了能够快速评估django-dash,创建了一个演示应用(带有快速安装程序)(适用于Ubuntu/Debian,可能在其他Linux系统上也能工作,尽管没有保证)。按照以下说明,在一分钟内运行演示。

获取最新的django_dash_example_app_installer.sh

wget https://raw.github.com/barseghyanartur/django-dash/stable/examples/django_dash_example_app_installer.sh

授予安装程序执行权限并运行django_dash_example_app_installer.sh

chmod +x django_dash_example_app_installer.sh

./django_dash_example_app_installer.sh

打开您的浏览器并测试该应用程序。

仪表板

Django管理界面

如果快速安装程序对您不起作用,请参阅在示例项目上运行的说明。

查看“example/example/templates”目录中的模板,以更好地了解如何将您自己的或第三方模板转换为Dash模板。

此外,示例项目实现了示例布局、插件和小部件。将其视为将小部件添加到现有插件的自定义布局的绝佳示例。确保查看如何为捆绑布局执行相同的操作。

安装

  1. 从PyPI安装最新稳定版本

    pip install django-dash

    或从GitHub安装最新稳定版本

    pip install https://github.com/barseghyanartur/django-dash/archive/stable.tar.gz

    或从BitBucket安装最新稳定版本

    pip install https://bitbucket.org/barseghyanartur/django-dash/get/stable.tar.gz
  2. dash 添加到您项目的 Django 设置中 INSTALLED_APPS。此外,所有要使用的布局和插件也应添加到 INSTALLED_APPS 中。

    INSTALLED_APPS = (
        # ...
        'dash',
        'dash.contrib.layouts.android',
        'dash.contrib.layouts.bootstrap2',
        'dash.contrib.layouts.windows8',
        'dash.contrib.plugins.dummy',
        'dash.contrib.plugins.image',
        'dash.contrib.plugins.memo',
        'dash.contrib.plugins.rss_feed',
        'dash.contrib.plugins.url',
        'dash.contrib.plugins.video',
        'dash.contrib.plugins.weather',
        # ...
    )
  3. 请确保 django.core.context_processors.request 包含在 TEMPLATE_CONTEXT_PROCESSORS 中。

  4. 将必要的 URL 模式添加到您的 urls 模块中。

    re_path(r'^dashboard/', include('dash.urls')),

    此外,添加任何 Dash 应用或插件的全部 URL。

    # django-dash RSS contrib plugin URLs:
    re_path(r'^dash/contrib/plugins/rss-feed/',
            include('dash.contrib.plugins.rss_feed.urls')),
    
    # django-dash public dashboards contrib app:
    re_path(r'^', include('dash.contrib.apps.public_dashboard.urls')),

创建新的布局

Dash 随带一些捆绑的布局。请检查它们的源代码作为示例。

假设我们的虚拟布局有两个占位符。一个用于各种小部件的大型占位符(称为 main),以及一个用于快捷方式的微型占位符(称为 shortcuts)。

占位符 main

  • 单个单元格大小:150 x 110 像素

  • 尺寸:6 列,5 行

占位符 shortcuts

  • 单个单元格大小:60 x 55 像素

  • 尺寸:1 列,10 行

见下面的图示,以了解占位符是什么。

  • 占位符 main 由 11 到 56 的单元格组成。

  • 占位符 shortcuts 由 1 到 10 的单元格组成。

单个插件小部件可能占据一个或多个单元格。插件小部件是矩形。

为了更清晰,请看以下情况

  • 插件小部件有 2 列和 1 行。例如,它可能占据单元格(11 和 12)。

  • 插件小部件有 2 列和 2 行。例如,它可能占据单元格(11,12,21 和 22)。

  • 插件小部件有 1 列和 3 行。例如,它可能占据单元格(11,21 和 31)。

  • 插件小部件有 4 列和 3 行。例如,它可能占据单元格(22,23,24,25,32,33,34,35,42,43,44 和 45)。

                                ``main``                               ``shortcuts``
┌───────────┬───────────┬───────────┬───────────┬───────────┬───────────┐ ┌─────┐
│           │           │           │           │           │           │ │  1  │
│           │           │           │           │           │           │ │     │
│    11     │    12     │    13     │    14     │    15     │    16     │ ├─────┤
│           │           │           │           │           │           │ │  2  │
│           │           │           │           │           │           │ │     │
├───────────┼───────────┼───────────┼───────────┼───────────┼───────────┤ ├─────┤
│           │           │           │           │           │           │ │     │
│           │           │           │           │           │           │ │  3  │
│    21     │    22     │    23     │    24     │    25     │    26     │ ├─────┤
│           │           │           │           │           │           │ │  4  │
│           │           │           │           │           │           │ │     │
├───────────┼───────────┼───────────┼───────────┼───────────┼───────────┤ ├─────┤
│           │           │           │           │           │           │ │     │
│           │           │           │           │           │           │ │  5  │
│    31     │    32     │    33     │    34     │    35     │    36     │ ├─────┤
│           │           │           │           │           │           │ │  6  │
│           │           │           │           │           │           │ │     │
├───────────┼───────────┼───────────┼───────────┼───────────┼───────────┤ ├─────┤
│           │           │           │           │           │           │ │     │
│           │           │           │           │           │           │ │  7  │
│    41     │    42     │    43     │    44     │    45     │    46     │ ├─────┤
│           │           │           │           │           │           │ │  8  │
│           │           │           │           │           │           │ │     │
├───────────┼───────────┼───────────┼───────────┼───────────┼───────────┤ ├─────┤
│           │           │           │           │           │           │ │     │
│           │           │           │           │           │           │ │  9  │
│    51     │    52     │    53     │    54     │    55     │    56     │ ├─────┤
│           │           │           │           │           │           │ │ 10  │
│           │           │           │           │           │           │ │     │
└───────────┴───────────┴───────────┴───────────┴───────────┴───────────┘ └─────┘

有一些规则/指南您应该遵循。

假设布局名为 example。那么布局目录应具有以下结构。

path/to/layout/example/
├── static
│   ├── css
│   │   └── dash_layout_example.css # Contains layout-specific CSS
│   ├── images
│   └── js
│       └── dash_layout_example.js # Contains layout specific JavaScripts
├── templates
│   └── example
│       ├── edit_layout.html # Master edit layout
│       └── view_layout.html # Master view layout
├── __init__.py
├── dash_layouts.py # Where layouts and placeholders are defined and registered
├── dash_plugins.py # Where layout specific plugins and plugin widgets are defined and registered
└── dash_widgets.py # Where layout specific plugin widgets are defined

布局和占位符类应放置在 dash_layouts.py 文件中。

每个布局都应该放入 Django 项目 settings.py 模块的 INSTALLED_APPS 中。

INSTALLED_APPS = (
    # ...
    'path.to.layout.example',
    # ...
)

path/to/layout/example/dash_layouts.py

逐步审查如何创建和注册布局和占位符。注意,Dash 通过 dash_layouts.py 文件的名称自动发现您的布局。定义布局的模块必须命名为 dash_layouts.py

必需的导入。

from dash.base import BaseDashboardLayout, BaseDashboardPlaceholder
from dash.base import layout_registry

定义主占位符。

class ExampleMainPlaceholder(BaseDashboardPlaceholder):

    uid = 'main'  # Unique ID of the placeholder.
    cols = 6  # Number of columns in the placeholder.
    rows = 5  # Number of rows in the placeholder.
    cell_width = 150  # Width of a single cell in the placeholder.
    cell_height = 110  # Height of a single cell in the placeholder.

定义快捷方式占位符。

class ExampleShortcutsPlaceholder(BaseDashboardPlaceholder):

    uid = 'shortcuts'  # UID of the placeholder.
    cols = 1  # Number of columns in the placeholder.
    rows = 10  # Number of rows in the placeholder.
    cell_width = 60  # Width of a single cell in the placeholder.
    cell_height = 55  # Height of a single cell in the placeholder.

定义和注册布局。

class ExampleLayout(BaseDashboardLayout):

    uid = 'example'  # Layout UID.
    name = 'Example'  # Layout name.

    # View template. Master template used in view mode.
    view_template_name = 'example/view_layout.html'

    # Edit template. Master template used in edit mode.
    edit_template_name = 'example/edit_layout.html'

    # All placeholders listed. Note, that placeholders are rendered in the
    # order specified here.
    placeholders = [ExampleMainPlaceholder, ExampleShortcutsPlaceholder]

    # Cell units used in the entire layout. Allowed values are: 'px',
    # 'pt', 'em' or '%'. In the ``ExampleMainPlaceholder`` cell_width is
    # set to 150. It means that in this particular case its' actual width
    # would be `150px`.
    cell_units = 'px'

    # Layout specific CSS.
    media_css = ('css/dash_layout_example.css',)

    # Layout specific JS.
    media_js = ('js/dash_layout_example.js',)

# Registering the layout.
layout_registry.register(ExampleLayout)

HTML 模板

您的自定义布局应继承自基础布局模板(查看或编辑)。查看和编辑布局有很多共同之处,但编辑布局要稍微复杂一些。

  • view_layout.html 应继承自 “dash/layouts/base_view_layout.html”。

  • edit_layout.html 应继承自 “dash/layouts/base_edit_layout.html”。

“dash/layouts/base_view_layout.html” 和 “dash/layouts/base_edit_layout.html” 都继承自 “dash/layouts/base_layout.html”,而后者又继承自 “dash/base.html”。

请注意,当渲染为 HTML 时,每个 Dash 模板都会获得一个包含“layout”+布局唯一标识符(UID)的 body 类。因此,ExampleLayout 布局将自动获得类“layout-example”。

<body class="layout-example">

对于 Android 布局(UID “android”),它将如下所示。

<body class="layout-android">

基于这些类的存在,创建您特定的自定义 CSS。

同样的规则也适用于占位符。每个占位符都会获得 id_ + 占位符的 UID 以及类名 “placeholder” 和 “placeholder-” + 占位符的 UID。所以,ExampleMainPlaceholder 的样子如下。

<div id="id_main" class="placeholder placeholder-main">

ExampleShortcutsPlaceholder 占位符的样子如下。

<div id="id_shortcuts" class="placeholder placeholder-shortcuts">

插件小部件也是如此。除了每个插件小部件为定位获得的某些其他类之外,它还会获得 “plugin” 和 “plugin-” + 插件 UID。以下是一个示例(对于 UID 为 “dummy” 的插件 Dummy)。每个插件在渲染时也会自动获得一个 UID。下面的示例中是 “p6d06f17d-e142-4f45-b9c1-893c38fc2b01”。

<div id="p6d06f17d-e142-4f45-b9c1-893c38fc2b01" class="plugin plugin-dummy">

布局、占位符、插件和插件小部件都有获取它们特定于 HTML 的类和 ID 的属性。

布局(实例)

layout.html_class

占位符(实例)

placeholder.html_id
placeholder.html_class

插件(实例)

plugin.html_id
plugin.html_class

插件小部件(静态调用)

plugin_widget.html_class  # Static one

创建新插件

Dash 随带了一些捆绑插件。请检查它们的源代码作为示例。

制作插件或插件小部件相当简单,尽管您应该遵循一些规则/指南。

假设插件名为 sample_memo。那么插件目录应该具有以下结构。

注意,建议您使用 dash_plugin_ 前缀来命名所有插件特定的媒体文件,这是出于常识的考虑。

path/to/plugin/sample_memo/
├── static
│   ├── css
│   │   └── dash_plugin_sample_memo.css # Plugin specific CSS
│   ├── images
│   └── js
│       └── dash_plugin_sample_memo.js # Plugin specific JavaScripts
├── templates
│   └── sample_memo
│       ├── render_main.html # Plugin widget template for ``main`` Placeholder
│       └── render_short.html # Plugin widget template for ``shortcuts`` Placeholder
├── __init__.py
├── dash_plugins.py # Where plugins and widgets are defined and registered
├── dash_widgets.py # Where the plugin widgets are defined
└── forms.py # Plugin configuration form

在某些情况下,您可能需要特定于插件的可覆盖设置(以 dash.contrib.plugins.weather 插件为例。建议您以这种方式编写设置,即您的 Django 项目 settings.py 模块中的变量具有 DASH_PLUGIN_ 前缀。

path/to/plugin/sample_memo/dash_plugins.py

逐步审查如何创建和注册插件和插件小部件。请注意,如果将插件放置在 Django 项目设置模块 INSTALLED_APPS 中列出的任何 Django 应用程序的 dash_plugins.py 文件中,Dash 会自动发现您的插件。

定义和注册插件

如前所述,单个插件小部件注册为一个三元组(布局、占位符、插件)。这意味着,如果您需要两个小部件,一个大小为 1x1,另一个大小为 2x2,则需要两个插件。您可以手动定义所有所需大小的小部件和插件,或者定义单个基本插件或小部件类,并将其工厂注册为给定大小的小部件。下面将解释这两种方法。

必需的导入。

from dash.base import BaseDashboardPlugin, plugin_registry
from path.to.plugin.sample_memo.forms import SampleMemoForm

定义 Sample Memo 插件(2x2)(在 main 占位符中使用)。

class SampleMemo2x2Plugin(BaseDashboardPlugin):

    uid = 'sample_memo_2x2'  # Plugin UID
    name = _("Memo")  # Plugin name
    group = _("Memo")  # Group to which the plugin belongs to
    form = SampleMemoForm  # Plugin forms are explained later
    html_classes = ['sample-memo']  # Optional. Adds extra HTML classes.

注册 Sample Memo 插件。

plugin_registry.register(SampleMemo2x2Plugin)

定义 Sample Memo 插件(1x1)(在 shortcuts 占位符中使用)。

class SampleMemo1x1Plugin(SampleMemo2x2Plugin):

    uid = 'sample_memo_1x1'  # Plugin UID

注册 Sample Memo 插件。

plugin_registry.register(SampleMemo1x1Plugin)

对于每个插件大小重复以下步骤(或阅读有关工厂注册插件和小部件的说明)。

工厂注册插件

或者,您可以定义一个单一的插件基类,并将其工厂注册为给定的大小。下面的代码将生成并注册大小为 1x1 和 2x2 的类。如果您需要注册 10 个大小的小部件,这种方法明显胜出。此外,它很容易清楚地了解所有注册的插件大小。

必需的导入。

from dash.base import BaseDashboardPlugin
from dash.factory import plugin_factory
from path.to.plugin.sample_memo.forms import SampleMemoForm

定义基插件类。

class BaseSampleMemoPlugin(BaseDashboardPlugin):

    name = _("Memo")  # Plugin name
    group = _("Memo")  # Group to which the plugin belongs to
    form = SampleMemoForm  # Plugin forms are explained later
    html_classes = ['sample-memo']  # Optional. Adds extra HTML classes.

请注意,我们没有在基类中提供 uid 属性。

现在我们已经定义了基插件,将其工厂注册为给定的大小。

sizes = (
    (1, 1),
    (2, 2),
)
plugin_factory(BaseSampleMemoPlugin, 'sample_memo', sizes)

在上面的示例中,“sample_memo” 是插件的基本名称。大小信息将附加到它(“sample_memo_1x1”,“sample_memo_2x2”)。

注册插件小部件

插件小部件在 dash_widgets.py 模块中定义(稍后描述),但在 dash_plugins.py 中注册,这是 Dash 自动发现的。

必需的导入。

from dash.base import plugin_widget_registry
from path.to.plugin.sample_memo.dash_widgets import (
    SampleMemo1x1ExampleMainWidget,
    SampleMemo2x2ExampleMainWidget,
)

为布局 example 的占位符 main 注册 Sample Memo 插件小部件。

plugin_widget_registry.register(SampleMemo2x2ExampleMainWidget)

注册示例布局的快捷键占位符插件小部件。

plugin_widget_registry.register(SampleMemo1x1ExampleMainWidget)

path/to/plugin/sample_memo/dash_widgets.py

为什么要为定义小部件使用另一个文件?只是为了保持代码整洁,不那么混乱,虽然你可以在 dash_plugins.py 模块中完美地定义所有插件小部件,但建议将其分开。

请注意,dash_widgets.py 不是一个自动发现的文件模式。你应该在名为 dash_plugins.py 的模块中注册所有插件小部件。

定义和注册插件小部件

必需的导入。

from django.template.loader import render_to_string
from dash.base import BaseDashboardPluginWidget

示例布局的备忘录插件小部件(占位符 main)。

class SampleMemo2x2ExampleMainWidget(BaseDashboardPluginWidget):

    layout_uid = 'example'  # Layout for which the widget is written
    placeholder_uid = 'main'  # Placeholder within the layout for which
                              # the widget is written
    plugin_uid = 'sample_memo_2x2'  # Plugin for which the widget is
                                    # written
    cols = 2  # Number of widget columns
    rows = 2  # Number of widget rows

    def render(self, request=None):
        context = {'plugin': self.plugin}
        return render_to_string('sample_memo/render_main.html', context)

示例布局的备忘录插件小部件(占位符 shortcuts)。

class SampleMemo1x1ExampleShortcutWidget(SampleMemo2x2ExampleMainWidget):

    placeholder_uid = 'shortcuts'  # Placeholder within the layout for
                                   # which the widget is written
    cols = 1  # Number of widget columns
    rows = 1  # Number of widget rows

    def render(self, request=None):
        context = {'plugin': self.plugin}
        return render_to_string(
            'sample_memo/render_shortcuts.html', context
        )

工厂注册插件小部件

或者,你可以定义一个单一的插件小部件基类,并为其指定的大小进行工厂注册。下面的代码将为 1x1 和 2x2 大小生成和注册类。

必需的导入。

from django.template.loader import render_to_string
from dash.factory import plugin_widget_factory
from dash.base import BaseDashboardPluginWidget

定义基插件小部件类。

class BaseSampleMemoWidget(BaseDashboardPluginWidget):

    def render(self, request=None):
        context = {'plugin': self.plugin}
        return render_to_string('sample_memo/render.html', context)

现在我们已经定义了基插件,将其工厂注册为给定的大小。

sizes = (
    (1, 1),
    (2, 2),
)
plugin_widget_factory(
    BaseSampleMemoWidget, 'example', 'main', 'sample_memo', sizes
)

在上面的例子中

  • “sample_memo”是插件的基本名称,它应该与插件工厂给出的名称完全匹配。

  • “example”是布局的 uid,小部件正在为其注册。

  • “main”是占位符的 uid,小部件正在为其注册。

path/to/plugin/sample_memo/forms.py

插件表单是什么?非常简单——如果插件可配置,它就有表单。如果你需要在渲染特定表单时包含自定义 CSS 或 JavaScript,请使用 Django 的 class Media 指令在表单中。

必需的导入。

from django import forms
from dash.base import DashboardPluginFormBase

备忘录表单(为 Sample Memo 插件)。

class SampleMemoForm(forms.Form, DashboardPluginFormBase):

    plugin_data_fields = [
        ("title", ""),
        ("text", "")
    ]

    title = forms.CharField(label=_("Title"), required=False)
    text = forms.CharField(label=_("Text"), required=True,
                           widget=forms.widgets.Textarea)

    def __init__(self, *args, **kwargs):
        super(MemoForm, self).__init__(*args, **kwargs)

现在,确保你的布局和插件模块都已添加到项目的 Django settings.py 模块的 INSTALLED_APPS 中。

INSTALLED_APPS = (
    # ...
    'path.to.layout.example',
    'path.to.plugin.sample_memo',
    # ...
)

完成后,打开终端并输入以下命令。

./manage.py dash_sync_plugins

如果你的 HTTP 服务器正在运行,你将能够访问你的仪表板。

注意,你必须登录才能使用仪表板。如果你的新插件没有出现,将 Django 的本地设置模块(local_settings.py)中的 DASH_DEBUG 设置为 True,重新运行你的代码,并在控制台中检查错误通知。

插件和小部件工厂

通常,当你制作一个新插件时,也会为它制作基小部件。通过创建基小部件,你避免了代码的重复。请看下面的例子。

from dash.base import BaseDashboardPlugin

class BaseMemoPlugin(BaseDashboardPlugin):

    name = _("Memo")
    group = _("Memo")
    form = MemoForm

现在我们有了基插件,我们可以使用插件工厂生成和注册所需尺寸的插件类。

from dash.factory import plugin_factory
plugin_factory(BaseMemoPlugin, 'memo', ((5, 6), (6, 5), (6, 6)))

上面的代码将生成“memo_5x6”、“memo_6x5”和“memo_6x6”插件类,这些类是 BaseMemoPlugin 的子类,并在插件注册表中注册。uid 属性将自动生成。

对于小部件来说也是一样。

from dash.base import BaseDashboardPluginWidget

class BaseMemoWidget(BaseDashboardPluginWidget):

    def render(self, request=None):
        context = {'plugin': self.plugin}
        return render_to_string('memo/render.html', context)

现在我们有了基小部件,我们可以使用插件小部件工厂生成和注册所需尺寸的插件小部件类。

from dash.factory import plugin_widget_factory

plugin_widget_factory(
    BaseMemoWidget,
    'bootstrap2_fluid',
    'main',
    'memo',
    ((5, 6), (6, 5), (6, 6))
)

上面的代码将生成“memo_5x6”、“memo_6x5”和“memo_6x6”插件小部件类,这些类是 BaseMemoWidget 的子类,并在插件小部件注册表中注册。layout_uid、placeholder_uid、plugin_uid、cols 和 rows 属性将自动生成。

当然,会有一些情况下你不能使用工厂,例如,因为你的每个插件或小部件都与其他插件或小部件有所不同,但如果你发现自己多次子类化基小部件或插件而没有更改代码,那么可能是一个开始使用工厂的好时机。

布局、插件和部件概览

在创建自己的布局、插件和插件部件时,您可以根据需要自由使用API。在开发Dash的过程中,我发现以下实践很有用:

  • 创建新的插件时,始终创建一个基础插件类,所有特定尺寸的插件都从该类派生。

  • 在插件中创建基础插件部件(带有HTML模板),但不要在那里注册。使用工厂(dash.factory)生成和注册特定布局的插件部件——最好在布局模块中。

  • 如果您要将自定义插件添加到现有的捆绑布局(位于dash.contrib.layouts的布局),创建一个名为dash_custom的新模块(或您喜欢的任何其他名称),并在名为dash_plugins.py的模块中生成/注册特定布局的插件部件(不要忘记将其添加到INSTALLED_APPS,以便自动发现)。

权限

插件系统允许管理员指定每个插件的访问权限。Dash权限基于Django用户和用户组。访问权限可以通过Django管理后台(/administration/dash/dashboardplugin/)进行管理。请注意,您的管理URL前缀可能与示例中的不同(通常是“/admin/”,而示例中是“/administration/”)。如果用户没有访问插件的权限,即使它已被添加到仪表板,也不会在仪表板上显示(想象一下,您曾经授予所有用户使用新闻插件的权利,但后来决定将其限制为仅工作人员组)。请注意,超级用户可以访问所有插件。

        Plugin access rights management interface in Django admin
┌──────────────────────────────┬────────────────────┬─────────────────────┐
│ `Plugin`                     │ `Users`            │ `Groups`            │
├──────────────────────────────┼────────────────────┼─────────────────────┤
│ Video (big_video)            │ John Doe           │ Dashboard users     │
├──────────────────────────────┼────────────────────┼─────────────────────┤
│ TinyMCE memo (tinymce_memo)  │                    │ Dashboard users     │
├──────────────────────────────┼────────────────────┼─────────────────────┤
│ News (news)                  │ Oscar, John Doe    │ Staff members       │
├──────────────────────────────┼────────────────────┼─────────────────────┤
│ URL (url)                    │                    │ Dashboard users     │
├──────────────────────────────┼────────────────────┼─────────────────────┤
│ Video (video)                │                    │ Dashboard users     │
├──────────────────────────────┼────────────────────┼─────────────────────┤
│ Dummy (dummy)                │                    │ Testers             │
├──────────────────────────────┼────────────────────┼─────────────────────┤
│ Dummy (large_dummy)          │                    │ Testers             │
├──────────────────────────────┼────────────────────┼─────────────────────┤
│ Memo (big_memo)              │                    │ Dashboard users     │
└──────────────────────────────┴────────────────────┴─────────────────────┘

管理命令

有几个管理命令。

  • dash_find_broken_dashboard_entries。查找由于某些曾经存在于系统中的插件不再存在而导致的损坏的仪表板条目。

  • dash_sync_plugins。每次向Dash添加新插件时都应该运行此命令。

  • dash_update_plugin_data。在插件更改后,如果插件数据变得无效,这是一种更新现有插件数据的方法。为了使其正常工作,每个插件都应该实现一个update方法,其中发生数据更新。

调整

您可以在Django项目的settings.py模块中覆盖多个Dash设置

  • DASH_RESTRICT_PLUGIN_ACCESS(布尔值):如果设置为True,则启用(Django)dash插件的权限系统。默认为True。将此设置为False会使所有插件对所有用户可用。

  • DASH_ACTIVE_LAYOUT(字符串):活动(默认)布局UID。默认为“android”。

  • DASH_LAYOUT_CELL_UNITS(字符串):布局单元的允许值。默认为(“em”,“px”,“pt”,“%”)。

  • DASH_DISPLAY_AUTH_LINK(布尔值):如果设置为True,则在Dash下拉菜单中显示注销链接。默认为True。

有关特定contrib插件的调整,请参阅插件目录中的文档。

样式技巧

Font Awesome用于图标。按照惯例,所有font-awesome图标都放置在一个span内。除了它们的原始类之外,它们都应该获得一个额外的类“iconic”。在创建新布局或插件(HTML)时遵循此规则,因为它可以使样式变得简单,因为图标颜色可以在短时间内更改。

捆绑插件和布局

Dash附带了一些捆绑(演示)插件和布局,主要用来展示其功能。为了在不同的布局(主题)中工作,每个插件为单个布局注册了一个单一的小部件。可以注销捆绑的小部件并用自定义小部件替换。

捆绑插件

以下是对插件的简要概述。有关详细信息,请参阅每个插件的目录中的README.rst文件。

  • 虚拟插件。主要用于快速测试。尽管如此,它也是一个如何编写插件和部件的完美示例。

  • 图片插件。允许用户在仪表板上放置图片。如果您计划制作一个处理文件上传的插件,请先检查此插件的源代码。

  • 备忘录插件。允许用户在仪表板上放置简短笔记。

  • RSS源插件。允许用户将任何RSS源直接放入仪表板。

  • URL插件。允许用户在仪表板上放置链接。

  • 书签插件。允许用户在仪表板上放置书签。书签由管理员添加。

  • 视频插件。允许用户在仪表板上放置YouTube或Vimeo视频。

  • 天气插件。允许将天气部件放入仪表板。

演示插件

  • D3插件示例。展示了如何将D3.js图表转换为Dash插件。

  • Polychart2插件示例。展示了如何将Polychart2.js图表转换为Dash插件。

  • 新闻插件。展示了如何将您的Django新闻应用程序(其前端部分)嵌入到Dash插件小部件中。

捆绑布局

以下是对布局的简要概述。有关详细信息,请参阅每个布局目录中的README.rst文件。

  • Android(类似)布局。有两个占位符:主区域(6列 x 5行,每个区块尺寸150x110像素)和快捷方式(1列 x 10行,每个区块尺寸60x55像素)。

  • Bootstrap 2 fluid(类似)布局。有一个占位符:主区域(11列 x 9行,每个区块尺寸70x40像素)。

  • Windows 8(类似)布局。有两个占位符:主区域(6列 x 4行,每个区块尺寸140x135像素)和侧边栏(2列 x 4行,每个区块尺寸140x135像素)。

演示布局

  • 示例布局。有五个占位符:顶部(8列 x 1行,每个区块尺寸55x55像素)、右侧(3列 x 8行,每个区块尺寸55x55像素)、底部(8列 x 1行,每个区块尺寸55x55像素)、左侧(3列 x 8行,每个区块尺寸55x55像素)和主区域(5列 x 4行,每个区块尺寸110x95像素)。

命名规范

尽管您可以自由命名您的插件和部件(但您应遵守PEP-008),但已引入了一些命名规范,建议您遵循。

  • Example1x1Plugin:1x1示例插件
    • Example1x1AndroidMainWidget:1x1小部件用于1x1示例插件(布局Android,占位符‘main’)

    • Example1x1AndroidShortcutsWidget:1x1小部件用于1x1示例插件(布局Android,占位符‘shortcuts’)

    • Example1x1Windows8MainWidget:1x1小部件用于1x1示例插件(布局Windows 8,占位符‘main’)

    • Example1x1Windows8SidebarWidget:1x1小部件用于1x1示例插件(布局Windows 8,占位符‘sidebar’)

  • Example2x3Plugin:2x3示例插件
    • Example2x3Windows8MainWidget:2x3小部件用于2x3示例插件(布局Windows 8,占位符‘main’)

    • Example2x3Windows8SidebarWidget:2x3小部件用于2x3示例插件(布局Windows 8,占位符‘sidebar’)

  • Example6x1Plugin:6x1示例插件
    • Example6x1YourLayoutSidebarWidget:6x1小部件用于6x1示例插件(布局Your Layout,占位符‘main’)

调试

大部分错误都被记录了(DEBUG)。如果你编写了一个插件,但它没有出现在可用的插件列表中,请运行以下管理命令

./manage.py dash_sync_plugins

dash_sync_plugins 不仅将你的插件同步到数据库中,而且还是检查可能错误的好方法。

可用翻译

  • 荷兰语(核心和插件)

  • 俄语(核心和插件)

故障排除

测试

项目由测试覆盖(功能测试和浏览器测试)。

默认使用 Py.test 作为测试运行器。

要测试所有支持的 Python/Django 版本,请输入

tox

要测试特定环境,请输入

tox -e py35-django18

要测试你的工作环境,请输入

./runtests.py

要测试你的工作环境(使用 Django 测试运行器),请输入

./manage.py test dash

假设你已经安装了所有要求。如果没有,首先安装测试要求

pip install -r examples/requirements/test.txt

浏览器测试

对于浏览器测试,你可以选择(无头)Firefox 或(无头)Chrome。无头模式更快,但正常浏览器测试能告诉你更多(因为你能看到屏幕上确切发生了什么)。两种情况都需要一些努力,而且在安装方面都有缺点(尽管一旦安装它们就能完美运行)。

设置 Firefox

  1. 这里 下载最新版本的 geckodriver(“geckodriver-vX.XX.X-linux64.tar.gz”),并将其解压缩到某个位置(`tar -xvzf geckodriver-vX.XX.X-linux64.tar.gz`)。然后为 geckodriver 赋予可执行权限(`chmod +x geckodriver`),将 geckodriver 可执行文件移动到 `/usr/local/bin` 或系统 PATH 上的任何位置。

  2. FIREFOX_BIN_PATH 设置中指定 Firefox 的完整路径。示例

    FIREFOX_BIN_PATH = '/usr/lib/firefox/firefox'

    如果你将 FIREFOX_BIN_PATH 设置为 None,将使用系统 Firefox。

之后,你的 Selenium 测试将工作。

设置无头 Firefox

  1. 安装 xvfb 包,该包用于以无头模式启动 Firefox。

    sudo apt-get install xvfb
  2. 使用无头 Firefox 运行测试。

    ./scripts/runtests.sh

    或者使用无头 Firefox 运行 tox 测试。

    ./scripts/tox.sh

设置 Chrome

  1. 这里 下载最新版本的 chromedriver(“chromedriver_linux64.zip”),并将其解压缩到某个位置。然后为 chromedriver 赋予可执行权限(`chmod +x chromedriver`),将 chromedriver 可执行文件移动到 `/usr/local/bin` 或系统 PATH 上的任何位置。

  2. CHROME_DRIVER_EXECUTABLE_PATH 设置中指定 Chrome 的完整路径。示例

    CHROME_DRIVER_EXECUTABLE_PATH = '/usr/bin/chromedriver'

设置无头 Chrome

from selenium import webdriver
CHROME_DRIVER_OPTIONS = webdriver.ChromeOptions()
CHROME_DRIVER_OPTIONS.add_argument('-headless')
CHROME_DRIVER_OPTIONS.add_argument('-no-sandbox')
CHROME_DRIVER_OPTIONS.set_capability('chrome.binary', "/usr/bin/google-chrome")

CHROME_DRIVER_EXECUTABLE_PATH = '/usr/bin/chromedriver'

之后,你的 Selenium 测试将工作。

许可证

GPL-2.0-only OR LGPL-2.1-or-later

支持

对于任何问题,请通过在 作者 部分给出的电子邮件联系我。

作者

Artur Barseghyan <artur.barseghyan@gmail.com>

截图

Android 布局

以下展示了几个 Android 布局的截图。

仪表板工作区(查看模式),你可以看到以下插件被使用

  • URL 插件

  • TinyMCE Memo 插件

  • Memo 插件

  • 视频插件

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_view_1.png

仪表板工作区(编辑模式),是上述仪表板工作区的编辑模式。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_full_1.png

仪表板工作区(查看模式),你可以看到以下插件被使用

  • 新闻插件

  • RSS 插件

  • 虚拟插件

  • URL 插件

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_view_2.png

仪表板工作区(编辑模式),是上述仪表板工作区的编辑模式。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_full_2.png

仪表板工作区(编辑模式)是编辑模式下的空仪表板工作区。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_empty_1.png

选择要添加到仪表板工作区的工具栏

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_empty_add_widget_1.png

TinyMCE 插件小部件表单

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dash_plugin_tinymce_memo_add_1.png

添加了 TinyMCE 插件小部件的工作区仪表板(编辑模式)。菜单已展开。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_progress_with_menu_1.png

编辑全局仪表板设置的表单。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_settings_1.png

编辑当前仪表板工作区设置的表单。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_workspace_1.png

Bootstrap 2 流布局

以下是 Bootstrap 2 流布局的几个截图。

仪表板工作区(编辑模式)是编辑模式下的空仪表板工作区。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/bootstrap2_edit_dashboard_empty_2.png

工作区仪表板(编辑模式)- 已填充的工作区仪表板。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/bootstrap2_edit_dashboard_1.png

上文提到的仪表板工作区的仪表板工作区(查看模式)。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/bootstrap2_view_dashboad_1.png

上文提到的仪表板工作区的公共仪表板。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/bootstrap2_public_dashboard_1.png

编辑仪表板设置对话框。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/bootstrap2_edit_settings_1.png

气泡图、堆叠到分组条和太阳花分割(查看仪表板模式)。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/d3_sample_charts_view_dashboard.png

气泡图、堆叠到分组条和太阳花分割(编辑仪表板模式)。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/d3_sample_charts_edit_dashboard.png

示例布局

以下是示例布局的几个截图。

仪表板工作区(编辑模式)是编辑模式下的空仪表板工作区。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_empty_2_example_layout.png

工作区仪表板(编辑模式)- 上文提到的仪表板工作区填充了图片。

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_edit_full_3_example_layout.png

上文提到的仪表板工作区的仪表板工作区(查看模式)

https://github.com/barseghyanartur/django-dash/raw/master/docs/_static/dash/dashboard_view_3_example_layout.png

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪一个,请了解有关 安装包 的更多信息。

源分布

django-dash-0.6.1.tar.gz (991.9 kB 查看哈希值)

上传

构建分布

django_dash-0.6.1-py2.py3-none-any.whl (1.1 MB 查看哈希值)

上传 Python 2 Python 3

由以下机构支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面