Added views for editing/deleting VCMemberships

This commit is contained in:
Jeremy Stretch 2017-12-08 12:51:52 -05:00
parent a85b3aa69f
commit da2bff691b
5 changed files with 80 additions and 12 deletions

View File

@ -2219,8 +2219,12 @@ class VirtualChassisCreateForm(BootstrapMixin, forms.ModelForm):
self.fields['master'].queryset = Device.objects.filter(pk__in=candidate_pks) self.fields['master'].queryset = Device.objects.filter(pk__in=candidate_pks)
#
# VC memberships
#
class VCMembershipForm(BootstrapMixin, forms.ModelForm): class VCMembershipForm(BootstrapMixin, forms.ModelForm):
class Meta: class Meta:
model = VCMembership model = VCMembership
fields = ['device', 'position', 'priority'] fields = ['position', 'priority']

View File

@ -1507,7 +1507,7 @@ class VirtualChassis(models.Model):
return self.master.name return self.master.name
def get_absolute_url(self): def get_absolute_url(self):
return "{}?virtual_chassis={}".format(reverse('dcim:device_list'), self.pk) return self.master.get_absolute_url()
@property @property
def master(self): def master(self):
@ -1547,13 +1547,21 @@ class VCMembership(models.Model):
unique_together = ['virtual_chassis', 'position'] unique_together = ['virtual_chassis', 'position']
verbose_name = 'VC membership' verbose_name = 'VC membership'
def __str__(self):
return self.device.name
def clean(self): def clean(self):
# We have to call this here because it won't be called by VCMembershipForm
self.validate_unique()
# Check for master conflicts # Check for master conflicts
if getattr(self, 'virtual_chassis', None) and self.is_master: if getattr(self, 'virtual_chassis', None) and self.is_master:
master_conflict = VCMembership.objects.filter(virtual_chassis=self.virtual_chassis).first() master_conflict = VCMembership.objects.filter(
virtual_chassis=self.virtual_chassis, is_master=True
).exclude(pk=self.pk).first()
if master_conflict: if master_conflict:
raise ValidationError({ raise ValidationError(
'virtual_chassis': "{} has already been designated as the master for this virtual chassis. It must " "{} has already been designated as the master for this virtual chassis. It must be demoted before "
"be demoted before a new master can be assigned.".format(master_conflict.device) "a new master can be assigned.".format(master_conflict.device)
}) )

View File

@ -213,4 +213,8 @@ urlpatterns = [
url(r'^virtual-chassis/(?P<pk>\d+)/edit/$', views.VirtualChassisEditView.as_view(), name='virtualchassis_edit'), url(r'^virtual-chassis/(?P<pk>\d+)/edit/$', views.VirtualChassisEditView.as_view(), name='virtualchassis_edit'),
url(r'^virtual-chassis/(?P<pk>\d+)/delete/$', views.VirtualChassisDeleteView.as_view(), name='virtualchassis_delete'), url(r'^virtual-chassis/(?P<pk>\d+)/delete/$', views.VirtualChassisDeleteView.as_view(), name='virtualchassis_delete'),
# VC memberships
url(r'^vc-memberships/(?P<pk>\d+)/edit/$', views.VCMembershipEditView.as_view(), name='vcmembership_edit'),
url(r'^vc-memberships/(?P<pk>\d+)/delete/$', views.VCMembershipDeleteView.as_view(), name='vcmembership_delete'),
] ]

View File

@ -1859,6 +1859,10 @@ class VirtualChassisCreateView(PermissionRequiredMixin, View):
class _VCMembershipForm(forms.VCMembershipForm): class _VCMembershipForm(forms.VCMembershipForm):
device = ModelChoiceField(queryset=Device.objects.filter(pk__in=device_list)) device = ModelChoiceField(queryset=Device.objects.filter(pk__in=device_list))
class Meta:
model = VCMembership
fields = ['device', 'position', 'priority']
VCMembershipFormSet = modelformset_factory(model=VCMembership, form=_VCMembershipForm, extra=len(device_list)) VCMembershipFormSet = modelformset_factory(model=VCMembership, form=_VCMembershipForm, extra=len(device_list))
if '_create' in request.POST: if '_create' in request.POST:
@ -1902,3 +1906,18 @@ class VirtualChassisDeleteView(PermissionRequiredMixin, ObjectDeleteView):
permission_required = 'dcim.delete_virtualchassis' permission_required = 'dcim.delete_virtualchassis'
model = VirtualChassis model = VirtualChassis
default_return_url = 'dcim:device_list' default_return_url = 'dcim:device_list'
#
# VC memberships
#
class VCMembershipEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_vcmembership'
model = VCMembership
model_form = forms.VCMembershipForm
class VCMembershipDeleteView(PermissionRequiredMixin, ObjectDeleteView):
permission_required = 'dcim.delete_vcmembership'
model = VCMembership

View File

@ -1,11 +1,44 @@
{% extends 'utilities/obj_edit.html' %} {% extends 'utilities/obj_edit.html' %}
{% load form_helpers %} {% load form_helpers %}
{% block form %} {% block content %}
<div class="panel panel-default"> {{ block.super }}
<div class="panel-heading"><strong>{{ obj_type|capfirst }}</strong></div> <div class="row">
<div class="panel-body"> <div class="col-md-6 col-md-offset-3">
{% render_form form %} <h3>Memberships</h3>
<div class="panel panel-default">
<table class="table panel-body">
<tr class="table-headings">
<th>Device</th>
<th>Position</th>
<th>Master</th>
<th>Priority</th>
<th></th>
</tr>
{% for vcm in form.instance.memberships.all %}
<tr>
<td>
<a href="{{ vcm.device.get_absolute_url }}">{{ vcm.device }}</a>
</td>
<td>{{ vcm.position }}</td>
<td>{% if vcm.is_master %}<i class="fa fa-check"></i>{% endif %}</td>
<td>{{ vcm.priority|default:"" }}</td>
<td class="text-right">
{% if perms.dcim.change_vcmembership %}
<a href="{% url 'dcim:vcmembership_edit' pk=vcm.pk %}?return_url={% url 'dcim:virtualchassis_edit' pk=vcm.virtual_chassis.pk %}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit
</a>
{% endif %}
{% if perms.dcim.delete_vcmembership %}
<a href="{% url 'dcim:vcmembership_delete' pk=vcm.pk %}?return_url={% url 'dcim:virtualchassis_edit' pk=vcm.virtual_chassis.pk %}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}