Openstack中Dashboard的二次开发
来源:互联网 发布:约瑟夫环 知乎 编辑:程序博客网 时间:2024/05/29 09:05
原文:Tutorial: Building a Dashboard using Horizon
除了原文中翻译的内容,还有自己添加的一部分内容
本教程讨论如何使用Horizon中多样的组件(主要是tables和tabs)来建立一个dashboard和panel,包括和后端的数据交互。
做为一个例子,我将创建一个有一个实例标签的panel,这个标签有一个能和Nova的API进行数据交换的table。
注:本教程假设你已经搭建好了环境,这里有很多有帮助的教程。比如你可能想从Horizon quickstart guide或者Django tutorial这些教程开始。
1 创建一个dashboard控制面板
1.1 快速版本
Horizon提供了一套自定义管理命令来创建一个典型的基于dashboard的结构。下列命令产生了大部分的模板代码:
mkdir openstack_dashboard/dashboards/mydashboard./run_tests.sh -m startdash mydashboard \ --target openstack_dashboard/dashboards/mydashboardmkdir openstack_dashboard/dashboards/mydashboard/mypanel./run_tests.sh -m startpanel mypanel \ --dashboard=openstack_dashboard.dashboards.mydashboard \ --target=openstack_dashboard/dashboards/mydashboard/mypanel
你会注意到这些mydashboard和mypanel的目录下会自动的生成相关的文件。
1.2 结构
如果你用tree mydashboard
命令,你会看到如下的结构
mydashboard├── dashboard.py├── dashboard.pyc├── __init__.py├── __init__.pyc├── mypanel│ ├── __init__.py│ ├── panel.py│ ├── templates│ │ └── mypanel│ │ └── index.html│ ├── tests.py│ ├── urls.py│ └── views.py├── static│ └── mydashboard│ ├── css│ │ └── mydashboard.css│ └── js│ └── mydashboard.js└── templates └── mydashboard └── base.html
对于本教程,我们将不会处理关于 static
文件夹或者 tests.py
文件,就放在那里不用管就好了。
我们将继续增加我们自己的dashboard。
1.3 定义一个dashboard
打开 dashboard.py
文件,你会看到以下代码已经被自动生成了:
from django.utils.translation import ugettext_lazy as _import horizonclass Mydashboard(horizon.Dashboard): name = _("Mydashboard") slug = "mydashboard" panels = () # Add your panels here. default_panel = '' # Specify the slug of the dashboard's default panel.horizon.register(Mydashboard)
如果你想让你的dashboard的名字可以在其他地方看到,你可以修改 dashboard.py
文件中的name参数,比如你想把名字改为My Dashboard
name = _("My Dashboard")
dashboard类通常会包括name(dashboard对外所呈现的名称)和一个slug(被其它组件引用的内部名称), panel列表和默认的panel等等。下面的章节会涉及到如何增加一个panel
2. 创建一个panel
我们将创建一个panel并将它命名为My Panel.
2.1 结构
mypanel的文件夹在 openstack_dashboard/dashboards/mydashboard
下,它的结构如下:
mypanel ├── __init__.py ├── models.py ├── panel.py ├── templates │ └── mypanel │ └── index.html ├── tests.py ├── urls.py └── views.py
2.2 定义一个panel
上面指定的panel.py文件有一个特殊的意义,在一个dashboard中,dashboard类中指定的”panels属性”列出任何模块名字,将自动在 panel.py
文件中查找相应的记录。
打开 panel.py
文件中,会看到一些自动生成的代码:
from django.utils.translation import ugettext_lazy as _import horizonfrom openstack_dashboard.dashboards.mydashboard import dashboardclass Mypanel(horizon.Panel): name = _("Mypanel") slug = "mypanel"dashboard.Mydashboard.register(Mypanel)
一旦定义了它,我们还需要在dashboard中注册它,通常在panel.py文件末尾:
dashboard.Mydashboard.register(Mypanel)
如果你想让panel的名字在其他地方也可以看到,你可以修改 panel.py
文件中的name参数,比如你可以把名字修改为 My Panel:
name = _("My Panel")
再次打开 dashboard.py
文件,在 Mydashboard class 上方插入如下代码,这段代码定义了 Mygroup 类并且增加了一个名为mypanel的panel
class Mygroup(horizon.PanelGroup): slug = "mygroup" name = _("My Group") panels = ('mypanel',)
修改Mydashboard 类使其包含Mygroup ,并设置mypanel为默认的panel:
class Mydashboard(horizon.Dashboard): name = _("My Dashboard") slug = "mydashboard" panels = (Mygroup,) # Add your panels here. default_panel = 'mypanel' # Specify the slug of the default panel.
完整的 dashboard.py
文件如下:
from django.utils.translation import ugettext_lazy as _import horizonclass Mygroup(horizon.PanelGroup): slug = "mygroup" name = _("My Group") panels = ('mypanel',)class Mydashboard(horizon.Dashboard): name = _("My Dashboard") slug = "mydashboard" panels = (Mygroup,) # Add your panels here. default_panel = 'mypanel' # Specify the slug of the default panel.horizon.register(Mydashboard)
3 Tables,Tabs,Views
我们从table开始,把table和tab整合到一起,最后把它们统一合成到一个视图(view)中。
3.1 定义一个Table
Horizon提供了一个SelfHandlingForm DataTable
类,简化了绝大多数显示数据给最终用户的工作。我们将略去这里的结构,但是这里有很多的capabilities(不会翻译了。。)
创建一个tables.py
文件并增加如下代码:
from django.utils.translation import ugettext_lazy as _from horizon import tablesclass InstancesTable(tables.DataTable): name = tables.Column("name", verbose_name=_("Name")) status = tables.Column("status", verbose_name=_("Status")) zone = tables.Column('availability_zone', verbose_name=_("Availability Zone")) image_name = tables.Column('image_name', verbose_name=_("Image Name")) class Meta: name = "instances" verbose_name = _("Instances")
有几件事情发生了,我们创建了一个table子类,定义了四列。每列定义了它访问实例类的属性作为第一个参数,由于我们希望所有的事情都是可以被翻译的,我们给每列一个 verbose_name
标记它们可以被翻译。
最后我们添加了一个Meta类来定义一些描述table的元数据。
3.2 向table添加action
Horizon提供了三种基本的可以呈现table数据的action类:
- Action
- LinkAction
- FilterAction
在基本的action的基础上,还提供了一些扩展的action类:
- BatchAction
- DeleteAction
- UpdateAction
- FixedFilterAction
现在,我们创建并向table添加一个“filter action”。我们需要编辑上面的table.py文件,添加了“filter action”后,我们将只能看到filter域中规定的字段。先定义一个FilterAction类:
class MyFilterAction(tables.FilterAction): name = "myfilter"
然后,我们将这个action加入到table中:
class InstancesTable: class Meta: table_actions = (MyFilterAction,)
完整的table.py文件看起来应该是这样:
from django.utils.translation import ugettext_lazy as _from horizon import tablesclass MyFilterAction(tables.FilterAction): name = "myfilter"class InstancesTable(tables.DataTable): name = tables.Column('name', \ verbose_name=_("Name")) status = tables.Column('status', \ verbose_name=_("Status")) zone = tables.Column('availability_zone', \ verbose_name=_("Availability Zone")) image_name = tables.Column('image_name', \ verbose_name=_("Image Name")) class Meta: name = "instances" verbose_name = _("Instances") table_actions = (MyFilterAction,)
3.3 定义tabs
因为我们有了table,可以接收数据,我们可以直接得到一个视图,这种情况下,我们同样适用Horizon的TabGroup类,它给我们一个干净、简化的tabs接口来显示我们的可视化数据。
在mypanel目录下创建tabs.py
文件,让我们整合table与tab,完整的代码如下:
from django.utils.translation import ugettext_lazy as _from horizon import exceptionsfrom horizon import tabsfrom openstack_dashboard import apifrom openstack_dashboard.dashboards.mydashboard.mypanel import tablesclass InstanceTab(tabs.TableTab): name = _("Instances Tab") slug = "instances_tab" table_classes = (tables.InstancesTable,) template_name = ("horizon/common/_detail_table.html") preload = False def has_more_data(self, table): return self._has_more def get_instances_data(self): try: marker = self.request.GET.get( tables.InstancesTable._meta.pagination_param, None) instances, self._has_more = api.nova.server_list( self.request, search_opts={'marker': marker, 'paginate': True}) return instances except Exception: self._has_more = False error_message = _('Unable to get instances') exceptions.handle(self.request, error_message) return []class MypanelTabs(tabs.TabGroup): slug = "mypanel_tabs" tabs = (InstanceTab,) sticky = True
这个tab有一点复杂。tab处理tables的数据(以及所有有关的特性),同时它可以使用preload属性来指定这个tab该不该被加载,默认情况下为不加载。当有人点击它时,它将通过AJAX方式加载,在绝大多数情况下保存我们的API调用。
此外,table的展示是由一个可重复使用的模板控制的,horizon/common/_detail_table.html
一些翻页的代码已经被增加进去了,来处理大量的实例列表。
最后,这个代码引进了错误处理,horizon.exceptions.handle()
这个函数是一个集中的错误处理机制,被广泛的使用。
3.4 把他们整合到一个视图(view)中
在Horizon中,有很多基于类的预建视图,我们试着给所有通用整合组件提供起始点。
打开 views.py
文件,代码看起来应该是这样:
from horizon import viewsclass IndexView(views.APIView): # A very simple class-based view... template_name = 'mydashboard/mypanel/index.html' def get_data(self, request, context, *args, **kwargs): # Add data to the context here... return context
class IndexView(tabs.TabbedTableView): tab_group_class = mydashboard_tabs.MypanelTabs
在引入合适的包之后,完整的 views.py
文件是这样的:
from horizon import tabsfrom openstack_dashboard.dashboards.mydashboard.mypanel \ import tabs as mydashboard_tabsclass IndexView(tabs.TabbedTableView): tab_group_class = mydashboard_tabs.MypanelTabs template_name = 'mydashboard/mypanel/index.html' def get_data(self, request, context, *args, **kwargs): # Add data to the context here... return context
4. URLs
自动生成的 url.py
文件如下:
from django.conf.urls import patternsfrom django.conf.urls import urlfrom openstack_dashboard.dashboards.mydashboard.mypanel.views \ import IndexViewurlpatterns = patterns( '', url(r'^$', IndexView.as_view(), name='index'),)
调整引入的包 IndexView
,增强文件的可读性
from openstack_dashboard.dashboards.mydashboard.mypanel import views
用下面的代码来替代已经存在的 url pattern
:
url(r'^$', views.IndexView.as_view(), name='index'),
完整的url.py
文件如下:
from django.conf.urls import patternsfrom django.conf.urls import urlfrom openstack_dashboard.dashboards.mydashboard.mypanel import viewsurlpatterns = patterns('', url(r'^$', views.IndexView.as_view(), name='index'),)
5. Template(模板)
打开 mydashboard/mypanel/templates/mypanel directory
目录下的 index.html
文件,它自动生成了如下代码:
{% extends 'base.html' %}{% load i18n %}{% block title %}{% trans "Mypanel" %}{% endblock %}{% block page_header %} {% include "horizon/common/_page_header.html" with title=_("Mypanel") %}{% endblock page_header %}{% block main %}{% endblock %}
- Openstack中Dashboard的二次开发
- OpenStack Dashboard二次开发环境的搭建
- OpenStack(kilo)界面dashboard的二次开发(四)-国际化
- OpenStack(kilo)界面dashboard的二次开发(三)-增加Dashboard
- openstack dashboard的汉化
- openstack dashboard的汉化
- OpenStack(kilo)界面dashboard的二次开发(一)-增加Panel
- OpenStack(kilo)界面dashboard的二次开发(二)-增加PanelGroup
- 关于Dundas Dashboard的二次开发
- OpenStack Dashboard
- 如何在OpenStack Dashboard中创建网络
- openstack中dashboard下发neutron api过程
- openstack dashboard实例连接失败的解决办法
- openstack dashboard vip没有启动的问题解决
- openstack dashboard中实例运行按钮没有反应
- 安装OpenStack-dashboard
- 搞定Openstack和Dashboard
- openstack系列-Dashboard
- C# SuperWebSocket服务端学习(二)
- service跨进程远程通讯
- 2016/07/31 安装cocoapods 失败 原因:ruby 环境版本必须大雨2.2 --> 更新到2.3后重新安装
- Matlab 2016a和VS2013混合Dll编程步骤
- 365. Water and Jug Problem
- Openstack中Dashboard的二次开发
- excel导出导出
- 根目录下常用目录作用
- java的List集合
- 孤儿进程与僵尸进程
- javascript变量声明提升(hoisting)
- 7、多线程
- 数据结构实验之二叉树五:层序遍历
- Codeforces 543A. Writing Code DP