[ English | 中文 (简体, 中国) | русский | português (Brasil) | नेपाली | 한국어 (대한민국) | Indonesia | français | español | esperanto | English (United Kingdom) | Deutsch ]
Tutorial: Membangun Dashboard menggunakan Horizon¶
Tutorial ini mencakup cara menggunakan berbagai komponen di horizon untuk membuat contoh dasbor dan panel dengan tab yang memiliki tabel berisi data dari back end.
Sebagai contoh, kami akan membuat dasbor My Dash
baru dengan panel My Panel
yang memiliki tab Tab Instances
. Tab memiliki tabel yang berisi data yang ditarik oleh Nova instances API.
Catatan
Tutorial ini mengasumsikan Anda memiliki lingkungan devstack
atau openstack
dan berjalan. Ada berbagai sumber daya lain yang mungkin bermanfaat untuk dibaca terlebih dahulu. Sebagai contoh, Anda mungkin ingin memulai dengan :ref: quickstart atau`Django tutorial`_.
Membuat dasbor¶
Versi cepat¶
Horizon menyediakan perintah manajemen khusus untuk membuat struktur dasbor dasar khas untuk Anda. Jalankan perintah berikut di direktori root Horizon Anda. Ini menghasilkan sebagian besar kode boilerplate yang Anda butuhkan:
$ mkdir openstack_dashboard/dashboards/mydashboard
$ tox -e manage -- startdash mydashboard \
--target openstack_dashboard/dashboards/mydashboard
$ mkdir openstack_dashboard/dashboards/mydashboard/mypanel
$ tox -e manage -- startpanel mypanel \
--dashboard=openstack_dashboard.dashboards.mydashboard \
--target=openstack_dashboard/dashboards/mydashboard/mypanel
Anda akan melihat bahwa direktori mydashboard
secara otomatis diisi dengan file yang terkait dengan dasbor dan direktori mypanel
secara otomatis diisi dengan file yang terkait dengan panel.
Structure (struktur)¶
Jika Anda menggunakan perintah tree mydashboard
untuk membuat daftar direktori mydashboard
di openstack_dashboard/dashboards
, Anda akan melihat struktur direktori yang terlihat seperti berikut
mydashboard
├── dashboard.py
├── __init__.py
├── mypanel
│ ├── __init__.py
│ ├── panel.py
│ ├── templates
│ │ └── mypanel
│ │ └── index.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── static
│ └── mydashboard
│ ├── scss
│ │ └── mydashboard.scss
│ └── js
│ └── mydashboard.js
└── templates
└── mydashboard
└── base.html
Untuk tutorial ini, kita tidak akan berurusan dengan direktori statis, atau file tests.py
. Biarkan mereka apa adanya.
Dengan sisa file dan direktori di tempatnya, kita dapat melanjutkan untuk menambahkan dasbor kita sendiri.
Menentukan dasbor¶
Buka file dashboard.py
. Anda akan melihat kode berikut telah dihasilkan secara otomatis:
from django.utils.translation import gettext_lazy as _
import horizon
class 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)
Jika Anda ingin nama dasbor menjadi sesuatu yang lain, Anda dapat mengubah atribut name
dalam file dashboard.py
. Misalnya, Anda dapat mengubahnya menjadi My Dashboard
name = _("My Dashboard")
Kelas dashboard biasanya akan berisi atribut name
(nama tampilan dashboard), atribut slug
(nama internal yang dapat dirujuk oleh komponen lain), daftar panel, panel default, dll. Kami akan membahas cara menambahkan panel di bagian selanjutnya.
Membuat panel¶
Kami akan membuat panel dan menyebutnya My Panel
.
Structure (struktur)¶
Seperti dijelaskan di atas, direktori mypanel
di bawah openstack_dashboard/dashboards/mydashboard
akan terlihat seperti berikut
mypanel
├── __init__.py
├── panel.py
├── templates
│ └── mypanel
│ └── index.html
├── tests.py
├── urls.py
└── views.py
Mendefinisikan panel¶
File panel.py
yang dirujuk di atas memiliki arti khusus. Di dalam dasbor, setiap nama modul yang tercantum dalam atribut panel
pada kelas dasbor akan ditemukan secara otomatis dengan mencari file panel.py
di direktori yang sesuai (detailnya agak ajaib, tetapi telah diperiksa secara menyeluruh dalam basis kode admin Django).
Buka file panel.py
, Anda akan memiliki kode yang dibuat secara otomatis berikut:
from django.utils.translation import gettext_lazy as _
import horizon
from openstack_dashboard.dashboards.mydashboard import dashboard
class Mypanel(horizon.Panel):
name = _("Mypanel")
slug = "mypanel"
dashboard.Mydashboard.register(Mypanel)
Jika Anda ingin nama panel menjadi sesuatu yang lain, Anda dapat mengubah atribut name
dalam file panel.py
. Misalnya, Anda dapat mengubahnya menjadi My Panel
:
name = _("My Panel")
Buka file dashboard.py
lagi, masukkan kode berikut di atas kelas Mydashboard
. Kode ini mendefinisikan kelas Mygroup
dan menambahkan panel yang disebut mypanel
class Mygroup(horizon.PanelGroup):
slug = "mygroup"
name = _("My Group")
panels = ('mypanel',)
Ubah kelas Mydashboard
untuk memasukkan Mygroup
dan tambahkan mypanel
sebagai panel default:
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.
File dashboard.py
yang telah selesai akan terlihat seperti berikut:
from django.utils.translation import gettext_lazy as _
import horizon
class 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)
Tables, Tabs, dan Views¶
Kami akan mulai dengan tabel, menggabungkan itu dengan tab, dan kemudian membangun tampilan (view) kami dari potongan.
Mendefinisikan tabel¶
Horizon menyediakan kelas SelfHandlingForm
DataTable
yang menyederhanakan sebagian besar menampilkan data ke end-user. Kami hanya akan membaca sekilas permukaannya di sini, tetapi ia memiliki sejumlah kemampuan yang luar biasa. Buat file tables.py
di bawah direktori mypanel
dan tambahkan kode berikut:
from django.utils.translation import gettext_lazy as _
from horizon import tables
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(object):
name = "instances"
verbose_name = _("Instances")
Ada beberapa hal yang terjadi di sini ... kami membuat subkelas tabel, dan mendefinisikan empat kolom yang ingin kami ambil data dan tampilan. Masing-masing kolom menentukan atribut apa yang diaksesnya pada objek instance sebagai argumen pertama, dan karena kami ingin membuat semuanya diterjemahkan, kami memberikan setiap kolom verbose_name
yang ditandai untuk terjemahan.
Terakhir, kami menambahkan kelas Meta
yang menunjukkan objek meta yang menggambarkan tabel instances
.
Catatan
Ini sedikit penyederhanaan dari kenyataan bagaimana objek contoh sebenarnya terstruktur. Pada saat menerima, atribut diakses diperlukan langkah tambahan.
Menambahkan tindakan ke tabel¶
Horizon menyediakan tiga jenis kelas tindakan dasar yang dapat diambil pada data tabel:
Ada juga tindakan tambahan yang merupakan ekstensi dari basic Action classes:
Sekarang mari kita buat dan tambahkan aksi filter ke tabel. Untuk melakukannya, kita perlu mengedit file tables.py
yang digunakan di atas. Untuk menambahkan tindakan filter yang hanya akan menampilkan baris yang berisi string yang dimasukkan dalam bidang filter, pertama-tama kita harus mendefinisikan tindakan (action):
class MyFilterAction(tables.FilterAction):
name = "myfilter"
Catatan
Tindakan (action) yang ditentukan di atas akan default filter_type
menjadi "query"
. Ini berarti bahwa filter akan menggunakan penyortir tabel sisi klien.
Kemudian, kami menambahkan action itu ke tindakan tabel (table action) untuk tabel kami.
class InstancesTable:
class Meta(object):
table_actions = (MyFilterAction,)
File tables.py
yang sudah selesai akan terlihat seperti berikut:
from django.utils.translation import gettext_lazy as _
from horizon import tables
class 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(object):
name = "instances"
verbose_name = _("Instances")
table_actions = (MyFilterAction,)
Menentukan tab¶
Jadi kami punya tabel, siap menerima data kami. Kita bisa langsung melihat dari sini, tetapi dalam kasus ini kita juga akan menggunakan kelas horizon :class: ~ horizon.tabs.TabGroup.
Buat file tabs.py
di bawah direktori mypanel
. Mari kita membuat grup tab yang memiliki satu tab. Kode yang sudah selesai akan terlihat seperti berikut
from django.utils.translation import gettext_lazy as _
from horizon import exceptions
from horizon import tabs
from openstack_dashboard import api
from openstack_dashboard.dashboards.mydashboard.mypanel import tables
class 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 ini menjadi sedikit lebih rumit. Tab menangani tabel data (dan semua fitur terkait), dan juga menggunakan atribut preload
untuk menentukan bahwa tab ini tidak boleh dimuat secara default. Sebagai gantinya itu akan dimuat melalui AJAX ketika seseorang mengkliknya, menyelamatkan kami dari panggilan API di sebagian besar kasus.
Selain itu, tampilan tabel ditangani oleh templat yang dapat digunakan kembali, horizon/common/_detail_table.html
. Beberapa kode pagination sederhana ditambahkan untuk menangani daftar instance besar.
Terakhir, kode ini memperkenalkan konsep penanganan kesalahan di horizon. Fungsi horizon.exceptions.handle()
adalah mekanisme penanganan kesalahan terpusat yang menghilangkan semua dugaan dan inkonsistensi dari berurusan dengan pengecualian dari API. Gunakan di mana-mana.
Mengikatnya bersama dalam tampilan (view)¶
Ada banyak pre-built class-based view di horizon. Kami mencoba memberikan titik awal (starting point) untuk semua kombinasi komponen yang umum.
Buka file views.py
, kode yang dibuat secara otomatis seperti berikut:
from horizon import views
class 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
Dalam hal ini kami ingin jenis view awal yang berfungsi dengan tab dan tabel ... yang akan menjadi kelas :class: ~ horizon.tabs.TabbedTableView. Dibutuhkan yang terbaik dari kemampuan dinamis yang disediakan grup tab yang disediakan dan digabungkan dalam tindakan dan pembaruan AJAX yang mampu dilakukan tabel dengan hampir tidak ada pekerjaan di sisi pengguna. Ubah views.APIView
menjadi tabs.TabbedTableView
dan tambahkan MypanelTabs
sebagai kelas grup tab di kelas IndexView
:
class IndexView(tabs.TabbedTableView):
tab_group_class = mydashboard_tabs.MypanelTabs
Setelah mengimpor paket yang tepat, file views.py
yang telah selesai sekarang tampak seperti berikut:
from horizon import tabs
from openstack_dashboard.dashboards.mydashboard.mypanel \
import tabs as mydashboard_tabs
class 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
URLs¶
File urls.py
auto-generated seperti:
from django.urls import re_path
from openstack_dashboard.dashboards.mydashboard.mypanel import views
urlpatterns = [
re_path(r'^$', views.IndexView.as_view(), name='index'),
]
Templat¶
Buka file index.html
di direktori mydashboard/mypanel/templates/mypanel
, kode yang dibuat secara otomatis seperti berikut:
{% 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 %}
Blok main
harus diubah untuk memasukkan kode berikut:
<div class="row">
<div class="col-sm-12">
{{ tab_group.render }}
</div>
</div>
Jika Anda ingin mengubah judul file index.html
menjadi sesuatu yang lain, Anda dapat mengubahnya. Sebagai contoh, ubahlah menjadi My Panel
di bagian block title
. Jika Anda ingin title
di bagian block page_header
menjadi sesuatu yang lain, Anda dapat mengubahnya. Sebagai contoh, ubahlah menjadi My Panel
. Kode yang diperbarui bisa seperti:
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "My Panel" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("My Panel") %}
{% endblock page_header %}
{% block main %}
<div class="row">
<div class="col-sm-12">
{{ tab_group.render }}
</div>
</div>
{% endblock %}
Ini memberi kami judul halaman khusus, header, dan merender grup tab kami yang disediakan oleh tampilan.
Dengan semua kode kami di tempat, satu-satunya yang tersisa untuk dilakukan adalah mengintegrasikannya ke situs OpenStack Dashboard site. kami.
Catatan
Untuk informasi lebih lanjut tentang tampilan, URL, dan templat Django, silakan merujuk ke Django documentation.
Aktifkan dan tampilkan dasbor¶
Untuk membuat My Dashboard
muncul bersama dengan dashboard yang ada seperti Project
atau Admin
di horizon, Anda perlu membuat file bernama _50_mydashboard.py
di bawah openstack_dashboard/enabled
dan tambahkan berikut ini:
# The name of the dashboard to be added to HORIZON['dashboards']. Required.
DASHBOARD = 'mydashboard'
# If set to True, this dashboard will not be added to the settings.
DISABLED = False
# A list of applications to be added to INSTALLED_APPS.
ADD_INSTALLED_APPS = [
'openstack_dashboard.dashboards.mydashboard',
]
Jalankan dan periksa dasbor¶
Semuanya sudah ada, sekarang jalankan Horizon
pada port yang berbeda
$ tox -e runserver -- 0:9000
Pergi ke http://<your server>:9000
menggunakan browser. Setelah login sebagai admin Anda harus dapat melihat My Dashboard
muncul di sisi kiri di horizon. Klik itu, My Group
akan berkembang dengan My Panel
. Klik pada My Panel
, panel sebelah kanan akan menampilkan Instances Tab
yang memiliki tabel Instances
.
Jika Anda tidak melihat data contoh apa pun, Anda belum membuat instance apa pun. Pergi ke dasbor Project
-> Images
, pilih image kecil, misalnya, cirros-0.3.1-x86_64-uec
, klik Launch
dan masukkan Instance Name
, klik tombol Launch
. Itu harus membuat contoh jika OpenStack atau devstack diatur dengan benar. Setelah pembuatan instance berhasil, buka My Dashboard
lagi untuk memeriksa data.
Menambahkan tindakan kompleks ke tabel¶
Untuk tampilan yang lebih terperinci dalam menambahkan aksi tabel, yang membutuhkan formulir untuk mengumpulkan data, Anda dapat menelusuri tutorial :ref: tutorials-table-action.
Kesimpulan¶
Apa yang telah Anda pelajari di sini adalah dasar-dasar cara menulis antarmuka untuk proyek Anda sendiri berdasarkan komponen horizon yang disediakan.
If you have feedback on how this tutorial could be improved, please feel free to submit a bug against launchpad:%shorizon.