注:openstack horion項目和其餘的項目有所不一樣,它主要提供一套工具,咱們能夠本身定製開發咱們想要的dashboard(控制面板)。 javascript
翻譯自:http://docs.openstack.org/developer/horizon/topics/tutorial.html css
本教程討論如何使用Horizon中多樣的組件來創建一個dashboard和panel經過 數據表和tabs。 html
做爲例子,咱們講以Nova 實例化API爲基礎來建立一個新的可視化的dashboard經過一個"floking"面板經過不一樣的方式表示實例的數據。 java
你能夠找到一個參考實現的的代碼在github https://github.com/gabrielhurley/horizon_demo. python
注意:你或許須要先閱讀一些有幫助的資源,由於這是一個高級的教程。例如,你或許想開始Horizon quickstart guide 或者 Django tutorial. git
注意:你能夠建立一個panel而不是dashboard,而後整合它到一個已經存在的dashboard。看章節overrides 。 github
Horizon 提供了一套自定義管理命令來建立一個典型的基於dashboard的結構。下列的命令生成了大部分的模板代碼: ajax
./run_tests.sh -m sstartdash visualizations很是推薦你閱讀剩餘的章節來理解這個命令建立了什麼和爲何要建立。
dashboard(或者panel)推薦的結構適合於典型的Django應用佈局。咱們將命名咱們的dashboard "visualizations": shell
visualizations |--__init__.py |--dashboard.py |--templates/ |--static/dashboard.py模塊將經過使用Horizon包含咱們要使用的dashboard類;templates和static目錄分別是咱們的Django模板文件和靜態媒體文件。
在static和templates目錄中,不錯的命名空間應該是像這樣: django
templates/ |--visualizations/ static/ |--visualizations/ |--css/ |--js/ |--img/在那些文件和目錄的地方,咱們能夠繼續寫咱們本身的dashboard類。
一個dashboard類能夠極爲簡單(最少3行),至少定義一個name和一個slug:
import horizon class VizDash(horizon.Dashboard): name = _("Visualizations") slug = "visualizations"
在實踐中,一個dashboard類將一般包含更多的信息,例如一系列的panels。就是那些默認的panel,和任何訪問dashboard的權限:
class VizDash(horizon.Dashboard): name = _("Visualizations") slug = "visualizations" panels = ('flocking',) default_panel = 'flocking' permissions = ('openstack.roles.admin')
從以前構建的例子咱們也能夠想要定義一組panels共享一個主題並且在導航上有一個子標題:
class InstanceVisualizations(horizon.PanelGroup): slug = "instance_visualizations" name = _("Instance Visualizations") panels = ('flocking',) class VizDash(horizon.Dashboard): name = _("Visualizations") slug = "visualizations" panels = (InstanceVisualizations,) default_panel = 'flocking' permissions = ('openstack.roles.admin',)PanelGroup能夠添加到dashboard類的panels列表就像 panels的slug那樣。
一旦咱們的dashboard類完成,咱們須要作的是註冊它:
horizon.register(VizDash)這個操做的典型的位置是dashboard.py文件的底部,可是它能夠在任何的其餘地方,例如在一個重寫的文件中。
如今咱們已經有了咱們寫的dashboard,咱們也能夠建立咱們的panel。咱們講稱之爲"flocking"。
注意:你不須要爲了添加一個panel而寫一個dashboard。這個結構是爲了教程的完整性。
Horizon提供了一套自定義管理命令來建立一個典型的基於panel的結構。下面的命令生成大部分的模板代碼:
./run_test.sh -m startpanel flocking --dashboard=visualizations --target=autodashboard參數是必選的,告訴命令panel註冊的dashboard。target參數是可選的,auto意味着建立的panel文件應該在dashboard模塊內相對於當前的目錄(默認)。
很是推薦你閱讀剩餘的章節來理解這個命令建立了什麼和爲何要建立。
一個Panel是一個相對flat結構,dashboard的panel的templates在dashboard的templates目錄而不是在panel的templates目錄。繼續咱們的vizulaization/flocking例子,讓咱們看看它們應該看起來像:
# stand-alone panel structure flocking/ |--__init__.py |--panel.py |--urls.py |--views.py |--templates/ |--flocking/ |--index.html # panel-in-a-dashboard structure visualizations/ |--__init__.py |--dashboard.py |--flocking/ |--__init__.py |--panel.py |--urls.py |--views.py |--templates/ |--visualizations/ |--flocking/ |--index.html跟隨標準的Django命名規範。一樣工做在Django的自動模板查找特性下。
上面指定panel.py文件有一個特殊的意義。在一個dashboard中,任何模塊的名字排列了panels屬性在dashboard上將自動在panel.py文件中查找在相應的目錄(詳細狀況有些神奇,可是被完全的審查在Django的admin代碼庫中)。
在panel.py模塊中咱們定義咱們的 Panel類:
class Flocking(horizon.Panel): name = _("Flocking") slug = 'flocking'簡單吧?一旦咱們定義了它,咱們就在dashboard中註冊它:
from visualizations import dashboard dashboard.VizDash.register(Flocking)簡單! 你能夠設置更多的可選的自定義項目在Panel類中,可是聰明的建議是想一下默認下應該有什麼。
一個充滿智慧的設想就是Panel類能夠被找到在一個urls.py文件在你的panel目錄,咱們定義一個叫作index的視圖做爲panel的默認處理視圖。下面是你的urls.py看起來應該像:
from django.conf.urls.defaults import patterns, url from .views import IndexView urlpatterns = patterns('', url(r'^$', IndexView.as_view(), name='index') )這不是100%標準的Django代碼。這個例子(Horizon一般上)使用了基於類的視圖在Django1.3中被介紹,使代碼更加能重用。所以視圖類被import在上面的例子中,as_view()方法被調用在URL pattern。
固然,假定你有一個視圖類,而後帶咱們到寫panel中去。
如今咱們要去真正使人激動的部分了;在這以前的任何事情都是結構性的。
從高層次的視圖開始,咱們最終的目標是建立一個視圖(咱們的IndexView類)使用Horizion的DataTable類來展現數據,使用Horizon的TabGroup類給咱們一個用戶友好的分頁式的結構在瀏覽器中。
咱們將先開始table,整合它與tabs,而後創建咱們的視圖。
Horizon提供了一個DataTable類簡化了絕大多數的顯示數據給最終用戶。咱們這裏只是瀏覽表面,可是它有一個巨大數量的能力。
這種狀況下,咱們使用tables呈現數據,因此讓咱們開始定義咱們的table(一個tables.py模塊:
from horizon import tables class FlockingInstancesTable(tables.DataTable): host = tables.Column("OS-EXT-SRV-ATTR:host", verbose_name=_("Host")) tenant = tables.Column('tenant_name', verbose_name=_("Tenant")) user = tables.Column('user_name', verbose_name=_("user")) vcpus = tables.Column('flavor_vcpus', verbose_name =_("VCPUs")) memory - tables.Column('flavor_memory', verbose_name=_("Memory")) age = tables.Column('age', verbose_name=_("Age")) class Meta: name = "instances" verbose_name = _("Instances")有幾件事情發生了,咱們建立了一個table子類,定義了六列。每列定義了它訪問實例類的屬性做爲第一個參數,因爲咱們但願全部的事情都是能夠被翻譯的,咱們給沒列一個verbose_name標記它們能夠被翻譯。
最後,咱們添加了一個Meta類定義了一些屬性關於咱們的table,尤爲是(翻譯)verbose name,一個"slug"用來識別它。
注意:這裏簡化了實際中的實例對象的真是結構。訪問flavor,tenant,用戶屬性須要另外一個步驟,這塊的代碼能夠在代碼示例中看到在github上。
由於咱們有了table,能夠接受數據,咱們能夠直接的到一個視圖,可是咱們能夠考慮跟多。在這種狀況下咱們一樣適用Horizon的TabGroup類。它給咱們一個乾淨,簡化的tabs接口來顯示咱們的可視化和能夠的咱們的數據。
首先,創建咱們的tab
class VizTab(tabs.Tab) name = _("Visualization") slug = "viz" template_name = "visualizations/flocking/_flocking.html" def get_context_data(self, request): return None這是你能作的最簡單的。因爲咱們的可視化將使用AJAX來加載數據咱們不須要傳遞任何內容到template上,全部咱們須要作的是定義個須要使用的template的名字。
如今,咱們須要給咱們的數據table一個tab:
from .tables import FlockingInstancesTable class DataTab(tabs.TableTab): name = _("Data") slug = "data" table_classes = (FlockingInstancesTable,) preload = False def get_instances_data(self): try: instances = utils.get_instances_data(self.tab_group.request) except: instances = [] exceptions.handle(self.tab_group.request, _('Unable to retrieve instance list.')) return instances
tab稍微有點複雜。最重要的,tab指定類型-處理數據tables(全部有關的特性)-它可使用preload屬性來指定這個tab不該該被加載在默認的狀況下。它將經過AJAX加載當有人點擊它,保存咱們的API調用在絕大多數狀況下。
最後,代碼介紹了Horion中的錯誤處理的概念。horizon.exceptions.handle()功能集中的錯誤處理機制。
有不少基於類的預建視圖在Horizon。咱們試着提供起始點給全部的通用整合組件。
這種狀況下咱們想要一個起始的視圖類型與tab和tables一塊兒工做,那應該是TabbedTableView類,它很好的動態延時加載能力tab組提供並且混合在actions中,同時AJAX更新tables在用戶端沒有作任何工做。讓咱們看看代碼應該是什麼樣子:
from .tables import FlockingInstancesTable from .tabs import FlockingTabs class IndexView(tabs.TabbedTableView): tab_group_class = FlockingTabs table_class = FlockingInstanceTable template_name = 'visualizations/flocking/index.html'這提供了咱們100%的方法給咱們想要的,若是這個特殊的例子不包含一個額外的AJAX調用來回收咱們的可視化數據經過AJAX。所以咱們須要重寫類中的get方法來返回一個正確的數據給一個AJAX調用:
from .tables import FlockingInstancesTable from .tabs import FlockingTabs class IndexView(tabs.TabbedTableView): tab_group_class = FlockingTabs table_class = FlockingInstanceTable template_name = 'visualizations/flocking/index.html' def get(self, request, *args, **kwargs): if self.request.is_ajax() and self.request.GET.get("json", False): try: instances = utils.get_instances_data(self.request) except: instances = [] exceptions.handle(request, _('Unable to retrieve instance list.')) data = json.dumps([i._apiresource._info for i in instances]) return http.HttpResponse(data) else: return super(IndexView, self).get(request, *args, **kwargs)在這個例子中,咱們重寫了get()方法這樣若是不是一個AJAX請求可是有 咱們尋找的GET參數,返回咱們的實例數據用JSON格式;不然只是像日常同樣返回視圖功能。
這裏咱們須要三個模板:一個給視圖,一個給咱們的每一個兩個tabs。視圖模板能夠繼承其餘的dashboard:
{% extends 'syspanel/base.html' %} {% load il8n %} {% block title %}{% trans "Flocking" %}{% endblock %} {% block page_header %} {% include "horizon/common/_page_header.html" with title=_("Flocking") %} {% endblock page_header %} {% block syspanel_main %} <div class="row-fluid"> <div class="span12"> {{ tab_group.render }} </div> </div> {% endblock %}這給了咱們一個自定義的頁面標題,一個頭,和渲染視圖提供的tab組、
對於tabs,使用的table是重用的模板,"horizon/common/_detail_table.html"。這適合任何的只顯示一個table的tab。
第二個tab是一個隱藏的,可是它很是簡單並且能夠在github的例子中研究它。
每一個tab須要一個模板與它關聯。
經過這些本地的代碼,惟一的剩下的事情就是去整合它們到咱們的 OpenStack Dashboard網站。
大部分的人會依靠Horizon定製本身的Dashboard。因此,這個教程只是想說明它能夠被定製。
一個基於Horizon的網站形式是一個典型的Django項目:
site/ |--__init__.py |--manage.py |--demo_dashboard/ |--__init__.py |--models.py # required for Django even if unused |--settings.py |--templates/ |--static/demo_dashboard在咱們的python路徑下,settings.py文件將包含咱們的定製的Horizon配置。
有一些關鍵的事情你須要定製化你網站的配置文件:指定定製的dashboard和panels,獲取你的客戶端的異常類,和指定一個高級覆寫文件。
最基礎的事情是添加你本身的定製的dashboard使用HORIZON_CONFIG字典在配置文件中:
HORIZON_CONFIG = { 'dashboards': ('nova', 'syspanel', 'visualizations', 'settings',), }在這種狀況下,咱們使用了默認的Horizon配置而後添加了咱們的visualizations dashboard。注意這裏的名字就是pyhton路徑下dashboard的模塊的名字。它會找到咱們的dashboard.py文件在裏面,而後自動從這加載dashboard和它的panesl。
添加定製的錯誤處理給你的API客戶端很是的簡單。在這個例子中不是必須的。經過定製'exceptions'的值在HORIZON_CONFIG字典:
import my_api.exceptions as my_api 'exceptions': {'recoverable': [my_api.Error, my_api.ClientConnectionError], 'not_found': [my_api.NotFound], 'unauthorized': [my_api.NotAuthorized]}
重寫文件是"god-mode"dashboard編輯。經過一個重寫文件你能夠修改任何你想存在在代碼中的行爲。這個教程並不深刻,可是咱們只能說能力越大責任越大。
爲了指定一個重寫文件,你設置customization_module''值在HORIZON_CONFIG字典。
HORIZON_CONFIG = { 'customization_module': 'demo_dashboard.overrides' }這個文件可以添加dashboard,添加panel到存在的dashboard,重命名存在的dashboards和panels(或者改變他們的屬性),從存在的dashboard上刪除panels,等等。
咱們能夠說的跟多,可是隻會更加危險 ....
教程中的信息從不意味着給你一個能夠工做的dashboard,由於這裏涉及太多的javascript在可視化,這和Horizon自己是不相干的。
若是你想看到最終的產品,查找github例子。
clone repository 而後執行./run_tests.sh --runserver.這會給你一個能夠工做的dashboard使用了每個教程中的技巧。