此例子是基于ocata版本horizon的自定义了一个插件。帮助对于horizon自定义dashbaord及panel的了解。要求对Python、HTML和JavaScript(AngularJS)有基本的了解。
不用说,选择一个有意义的存储库名称很重要。此外,如果您计划在您的dashboard插件上支持翻译,建议选择一个类似于xxxx-dashboard的名称(或xxxx-ui. xxx-horizon)。OpenStack CI infra脚本将这些后缀视为Django项目。
文件结构
整个插件目录结构如下:
xxxx-dashboard│├── xxxxdashboard│ ├── __init__.py│ ││ ├── enabled│ │ ├──_90000_mydashboard.py│ │ ├──_90010_mygroup_panel_group.py│ │ └──_90011_mypanel.py│ ││ ├── api│ │ ├──__init__.py│ │ ├── my_rest_api.py│ │ └── myservice.py│ ││ ├── dashboards│ │ ├──__init__.py│ │ └── mydashboard│ │ ├──__init__.py│ │ ├──dashboard.py│ │ ├── mypanel│ │ │ ├── __init__.py│ │ │ ├── panel.py│ │ │ ├── tests.py│ │ │ ├── urls.py│ │ │ ├── views.py│ │ │ └── templates│ │ │ └── mypanel│ │ │ └── index.html│ │ └── static│ │ └── dashboard│ | └── mydashboard│ | └── mypanel│ | ├── mypanel.html│ | ├── mypanel.js│ | └── mypanel.scss│ | │ ││ └── locale│ └──│ └── LC_MESSAGES│ ├── django.po│ └── djangojs.po│├── setup.py├── setup.cfg├── LICENSE├── MANIFEST.in├── README.rst├── babel-django.cfg└── babel-djangojs.cfg
Enabled 文件
_90000_mydashboard.py
# The slug of the dashboard to be added to HORIZON['dashboards']. Required.DASHBOARD = 'mydashboard'# If set to True, this dashboard will be set as the default dashboard.#DEFAULT = True# A dictionary of exception classes to be added to HORIZON['exceptions'].ADD_EXCEPTIONS = {}# A list of applications to be added to INSTALLED_APPS.ADD_INSTALLED_APPS = [xxxxdashboard.dashboards.mydashboard']ADD_ANGULAR_MODULES = [ 'dashboard.mydashboard.mypanel',]AUTO_DISCOVER_STATIC_FILES = TrueADD_JS_FILES = []ADD_JS_SPEC_FILES = []
_90010_mygroup_panel_group.py
from django.utils.translation import ugettext_lazy as _# The slug of the panel group to be added to HORIZON_CONFIG. Required.PANEL_GROUP = 'mygroup'# The display name of the PANEL_GROUP. Required.PANEL_GROUP_NAME = _('MyGroup')# The slug of the dashboard the PANEL_GROUP associated with. Required.PANEL_GROUP_DASHBOARD = 'mydashboard'
_90011_mypanel.py
# The slug of the panel to be added to HORIZON_CONFIG. Required.PANEL = 'mypanel'# The slug of the dashboard the PANEL associated with. Required.PANEL_DASHBOARD = 'mydashboard'# The slug of the panel group the PANEL is associated with.PANEL_GROUP = 'mygroup'# If set, it will update the default panel of the PANEL_DASHBOARD.DEFAULT_PANEL = 'mypanel'# Python panel class of the PANEL to be added.ADD_PANEL = 'xxxxdashboard.dashboards.mydashboard.mypanel.panel.MyPanel'
dashboards
dashboard.py
from django.utils.translation import ugettext_lazy as _import horizonclass MyDashboard(horizon.Dashboard): name = _("MyDashboard") slug = "mydashboard"horizon.register(MyDashboard)
panel
panel.py
from django.utils.translation import ugettext_lazy as _import horizonclass MyPanel(horizon.Panel): name = _("My Panel") slug = "mypanel"
urls.py
from django.conf.urls import urlfrom xxxxdashboard.dashboards.mydashboard.mypanel import viewsurlpatterns = [ url(r'^$', views.IndexView.as_view(), name='index'),]
views.py
from django.views.generic import baseclass IndexView(base.TemplateView): template_name = 'mydashboard/mypanel/index.html'
index.html
此文件位于dashboards/mydashboard/mypanel/templates/mypanel/index.html。
{% extends 'base.html' %}{% load i18n %}{% block title %}{% trans "My panel" %}{% endblock %}{% block page_header %} {% include "horizon/common/_domain_page_header.html" with title=page_title %}{% endblock page_header %}{% block main %}{% endblock %}
静态文件的目录结构如果下图
mypanel.html
Loading data from your controller:
- {$ item.name $} {$ item.id $}
mypanel.js
(function() { 'use strict'; angular .module('dashboard.mydashboard.mypanel', []) .controller('dashboard.mydashboard.myPluginController', myPluginController); myPluginController.$inject = [ '$http' ]; function myPluginController($http) { var ctrl = this; ctrl.items = [ { name: 'abc', id: 123 }, { name: 'efg', id: 345 }, { name: 'hij', id: 678 } ]; }})();
mypanel.scss
li{ display: inline; margin-right: 15px; input[type="radio"] { margin: 0px; }}
MANIFEST.in
该文件负责列出您想要包含在tar中的路径.
include setup.pyrecursive-include myplugin *.js *.html *.scss
setup.py
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDITimport setuptools# In python < 2.7.4, a lazy loading of package `pbr` will break# setuptools if some other modules registered functions in `atexit`.# solution from: http://bugs.python.org/issue15881#msg170215try: import multiprocessing # noqaexcept ImportError: passsetuptools.setup( setup_requires=['pbr>=1.8'], pbr=True)
setup.cfg
[metadata]name = mypluginsummary = A panel plugin for OpenStack Dashboarddescription-file = README.rstauthor = mynameauthor_email = myemailhome-page = https://docs.openstack.org/horizon/latest/classifiers = [ Environment :: OpenStack Framework :: Django Intended Audience :: Developers Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3.5[files]packages = myplugin
来源: