[ English | 中文 (简体, 中国) | русский | português (Brasil) | नेपाली | 한국어 (대한민국) | Indonesia | français | español | esperanto | English (United Kingdom) | Deutsch ]

Tutorial: Menambahkan tindakan kompleks ke tabel

Tutorial ini mencakup cara menambahkan tindakan yang lebih kompleks ke tabel, yang membutuhkan tindakan dan definisi bentuk, serta perubahan pada tampilan, url, dan tabel.

Tutorial ini mengasumsikan Anda telah menyelesaikan :ref: tutorials-dashboard. Jika tidak, silakan lakukan sekarang karena kami akan memodifikasi file yang dibuat di sana.

Tindakan ini akan membuat snapshot dari instance. Ketika tindakan diambil, itu akan menampilkan formulir yang akan memungkinkan pengguna untuk memasukkan nama snapshot, dan akan membuat snapshot itu ketika formulir ditutup menggunakan tombol Create snapshot.

Menentukan view

Untuk menentukan view, kita harus membuat kelas view, bersama dengan file templat (HTML) dan kelas bentuk untuk view itu.

File template

File template berisi HTML yang akan digunakan untuk menampilkan view.

Buat file create_snapshot.html di bawah direktori mypanel/templates/mypanel dan tambahkan kode berikut

{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Create Snapshot" %}{% endblock %}

{% block page_header %}
  {% include "horizon/common/_page_header.html" with title=_("Create a Snapshot") %}
{% endblock page_header %}

{% block main %}
    {% include 'mydashboard/mypanel/_create_snapshot.html' %}
{% endblock %}

Seperti yang Anda lihat, isi utama akan didefinisikan dalam _create_snapshot.html, jadi kita juga harus membuat file itu di bawah direktori mypanel/templates/mypanel. Itu harus berisi kode berikut

{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}

{% block modal-body-right %}
    <h3>{% trans "Description:" %}</h3>
    <p>{% trans "Snapshots preserve the disk state of a running instance." %}</p>
{% endblock %}

The form

Horizon menyediakan kelas :class: ~ horizon.forms.base.SelfHandlingForm yang menyederhanakan beberapa detail yang terlibat dalam membuat formulir. Form kami akan berasal dari kelas ini, menambahkan bidang karakter untuk memungkinkan pengguna menentukan nama untuk snapshot itu, dan menangani penutupan form yang berhasil dengan memanggil api nova untuk membuat snapshot itu.

Buat file forms.py di bawah direktori mypanel dan tambahkan berikut

from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from horizon import exceptions
from horizon import forms

from openstack_dashboard import api


class CreateSnapshot(forms.SelfHandlingForm):
    instance_id = forms.CharField(label=_("Instance ID"),
                                  widget=forms.HiddenInput(),
                                  required=False)
    name = forms.CharField(max_length=255, label=_("Snapshot Name"))

    def handle(self, request, data):
        try:
            snapshot = api.nova.snapshot_create(request,
                                                data['instance_id'],
                                                data['name'])
            return snapshot
        except Exception:
            exceptions.handle(request,
                              _('Unable to create snapshot.'))

The view

Sekarang, view akan menyatukan templat dan form. Horizon menyediakan kelas ModalFormView yang menyederhanakan pembuatan view yang akan berisi form modal.

Buka file views.py di bawah direktori mypanel dan tambahkan kode untuk CreateSnapshotView dan impor yang diperlukan. File lengkap sekarang akan terlihat seperti ini

from django.urls import reverse
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _

from horizon import tabs
from horizon import exceptions
from horizon import forms

from horizon.utils import memoized

from openstack_dashboard import api

from openstack_dashboard.dashboards.mydashboard.mypanel \
    import forms as project_forms

from openstack_dashboard.dashboards.mydashboard.mypanel \
    import tabs as mydashboard_tabs


class IndexView(tabs.TabbedTableView):
    tab_group_class = mydashboard_tabs.MypanelTabs
    # 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 CreateSnapshotView(forms.ModalFormView):
    form_class = project_forms.CreateSnapshot
    template_name = 'mydashboard/mypanel/create_snapshot.html'
    success_url = reverse_lazy("horizon:project:images:index")
    modal_id = "create_snapshot_modal"
    modal_header = _("Create Snapshot")
    submit_label = _("Create Snapshot")
    submit_url = "horizon:mydashboard:mypanel:create_snapshot"

    @memoized.memoized_method
    def get_object(self):
        try:
            return api.nova.server_get(self.request,
                                       self.kwargs["instance_id"])
        except Exception:
            exceptions.handle(self.request,
                              _("Unable to retrieve instance."))

    def get_initial(self):
        return {"instance_id": self.kwargs["instance_id"]}

    def get_context_data(self, **kwargs):
        context = super(CreateSnapshotView, self).get_context_data(**kwargs)
        instance_id = self.kwargs['instance_id']
        context['instance_id'] = instance_id
        context['instance'] = self.get_object()
        context['submit_url'] = reverse(self.submit_url, args=[instance_id])
        return context

Menambahkan url

Kami harus menambahkan url untuk view baru kami. Buka file urls.py di bawah direktori mypanel dan tambahkan berikut ini sebagai pola url baru

url(r'^(?P<instance_id>[^/]+)/create_snapshot/$',
    views.CreateSnapshotView.as_view(),
    name='create_snapshot'),

File urls.py yang lengkap harus terlihat seperti ini

from django.urls import re_path

from openstack_dashboard.dashboards.mydashboard.mypanel import views


urlpatterns = [
    re_path(r'^$',
            views.IndexView.as_view(), name='index'),
    re_path(r'^(?P<instance_id>[^/]+)/create_snapshot/$',
            views.CreateSnapshotView.as_view(),
            name='create_snapshot'),
]

Tentukan tindakannya (action)

Horizon menyediakan kelas :class: ~ horizon.tables.LinkAction yang menyederhanakan menambahkan action yang dapat digunakan untuk menampilkan view lain.

Kami akan menambahkan action tautan ke tabel yang akan dapat diakses dari setiap baris di tabel. Action akan menggunakan view yang ditentukan di atas untuk membuat snapshot dari instance yang diwakili oleh baris dalam tabel.

Untuk melakukan ini, kita harus mengedit file tables.py di bawah direktori mypanel dan menambahkan berikut

def is_deleting(instance):
    task_state = getattr(instance, "OS-EXT-STS:task_state", None)
    if not task_state:
        return False
    return task_state.lower() == "deleting"


class CreateSnapshotAction(tables.LinkAction):
    name = "snapshot"
    verbose_name = _("Create Snapshot")
    url = "horizon:mydashboard:mypanel:create_snapshot"
    classes = ("ajax-modal",)
    icon = "camera"

    # This action should be disabled if the instance
    # is not active, or the instance is being deleted
    def allowed(self, request, instance=None):
        return instance.status in ("ACTIVE") \
            and not is_deleting(instance)

Kita juga harus menambahkan tindakan baru kita sebagai tindakan baris untuk tabel

row_actions = (CreateSnapshotAction,)

File tables.py yang lengkap harus terlihat seperti ini

from django.utils.translation import gettext_lazy as _

from horizon import tables


def is_deleting(instance):
    task_state = getattr(instance, "OS-EXT-STS:task_state", None)
    if not task_state:
        return False
    return task_state.lower() == "deleting"


class CreateSnapshotAction(tables.LinkAction):
    name = "snapshot"
    verbose_name = _("Create Snapshot")
    url = "horizon:mydashboard:mypanel:create_snapshot"
    classes = ("ajax-modal",)
    icon = "camera"

    def allowed(self, request, instance=None):
        return instance.status in ("ACTIVE") \
            and not is_deleting(instance)


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,)
        row_actions = (CreateSnapshotAction,)

Jalankan dan periksa dasbor

Kami sekali lagi harus menjalankan horizon untuk memverifikasi dasbor Anda berfungsi

$ tox -e runserver -- 0:9000

Pergi ke http://<your server>:9000 menggunakan browser. Setelah login sebagai admin, tampilkan My Panel untuk melihat tabel Instances. Untuk setiap instance ACTIVE dalam tabel, akan ada tindakan Create Snapshot di baris. Klik Create Snapshot, masukkan nama snapshot dalam form yang ditampilkan, lalu klik untuk menutup form. View Project Images harus ditampilkan dengan snapshot baru ditambahkan ke tabel.

Kesimpulan

Apa yang telah Anda pelajari di sini adalah dasar-dasar cara menambahkan tindakan tabel yang membutuhkan form untuk entri data. Ini dapat dengan mudah diperluas dari membuat snapshot ke panggilan API lain yang membutuhkan form yang lebih kompleks untuk mengumpulkan informasi yang diperlukan.

If you have feedback on how this tutorial could be improved, please feel free to submit a bug against launchpad:%shorizon.