{% trans "Snapshots preserve the disk state of a running instance." %}
{% endblock %} The form -------- Horizon provides a :class:`~horizon.forms.base.SelfHandlingForm` class which simplifies some of the details involved in creating a form. Our form will derive from this class, adding a character field to allow the user to specify a name for the snapshot, and handling the successful closure of the form by calling the nova api to create the snapshot. Create the ``forms.py`` file under the ``mypanel`` directory and add the following:: from django.urls import reverse from django.utils.translation import ugettext_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 -------- Now, the view will tie together the template and the form. Horizon provides a :class:`~horizon.forms.views.ModalFormView` class which simplifies the creation of a view that will contain a modal form. Open the ``views.py`` file under the ``mypanel`` directory and add the code for the CreateSnapshotView and the necessary imports. The complete file should now look something like this:: from django.urls import reverse from django.urls import reverse_lazy from django.utils.translation import ugettext_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 Adding the url ============== We must add the url for our new view. Open the ``urls.py`` file under the ``mypanel`` directory and add the following as a new url pattern:: url(r'^(?PY??µ@cAAÀBpC CÐD‚E4EçFšGOHH»IqJ+JäKžLZMMÓN’ORPPÖQ™R^S$SêT±UzVEWWÚX¦YsZB[[Ö\Ÿ]h^2^û_Å`‘a\b)böcÄd“eaf3ggÖhªijTk,llßmºn˜owpWq:rssìtÕuÁv¯wžxyzw{k|d}]~XT€RQ‚QƒR„T…Y†]‡eˆk‰sŠ‹ˆŒ’žŽ©¶Ã‘Ñ’Þ“î•–)—\˜™Åšûœ.bž•ŸÊ ü¢2£e¤š¥Ï§¨<©wª¯«ë*®j¯ª°ï²6³€´Ì¶·l¸Äº»¼â¾L¿¼Á1¬Ä+űÇBÈÚÊxÌÍÐÏÑTÓ&Õ