implement assign device for rack

This commit is contained in:
Alex Gittings 2022-03-15 12:30:48 +00:00
parent 1add5accf2
commit 1a817619c7
9 changed files with 179 additions and 1 deletions

View File

@ -29,6 +29,7 @@ __all__ = (
'DeviceBayForm', 'DeviceBayForm',
'DeviceBayTemplateForm', 'DeviceBayTemplateForm',
'DeviceForm', 'DeviceForm',
'DeviceAssignForm',
'DeviceRoleForm', 'DeviceRoleForm',
'DeviceTypeForm', 'DeviceTypeForm',
'DeviceVCMembershipForm', 'DeviceVCMembershipForm',
@ -631,6 +632,23 @@ class DeviceForm(TenancyForm, CustomFieldModelForm):
self.fields['position'].widget.choices = [(position, f'U{position}')] self.fields['position'].widget.choices = [(position, f'U{position}')]
class DeviceAssignForm(BootstrapMixin, forms.Form):
rack_id = DynamicModelMultipleChoiceField(
queryset=Rack.objects.all(),
required=False,
null_option='None',
query_params={
'site_id': '$site_id',
'location_id': '$location_id',
},
label=_('Rack')
)
q = forms.CharField(
required=False,
label='Search',
)
class CableForm(TenancyForm, CustomFieldModelForm): class CableForm(TenancyForm, CustomFieldModelForm):
tags = DynamicModelMultipleChoiceField( tags = DynamicModelMultipleChoiceField(
queryset=Tag.objects.all(), queryset=Tag.objects.all(),

View File

@ -163,8 +163,9 @@ class RackElevationSVG:
'position': id_ 'position': id_
}) })
) )
return_url = "&return_url={}".format(rack.get_absolute_url())
link = drawing.add( link = drawing.add(
drawing.a(href=link_url, target='_top') drawing.a(href=link_url+"{}".format(return_url), target='_top')
) )
if reservation: if reservation:
link.set_desc('{}{} · {}'.format( link.set_desc('{}{} · {}'.format(

View File

@ -30,6 +30,7 @@ __all__ = (
'DeviceRearPortTable', 'DeviceRearPortTable',
'DeviceRoleTable', 'DeviceRoleTable',
'DeviceTable', 'DeviceTable',
'DeviceAssignTable',
'FrontPortTable', 'FrontPortTable',
'InterfaceTable', 'InterfaceTable',
'InventoryItemTable', 'InventoryItemTable',
@ -213,6 +214,40 @@ class DeviceTable(BaseTable):
) )
class DeviceAssignTable(BaseTable):
name = tables.TemplateColumn(
template_code=DEVICE_ASSIGN_LINK,
verbose_name='Name'
)
status = ChoiceFieldColumn()
tenant = TenantColumn()
site = tables.Column()
location = tables.Column()
rack = tables.Column()
device_role = ColoredLabelColumn(
verbose_name='Role'
)
manufacturer = tables.Column(
accessor=Accessor('device_type__manufacturer'),
)
device_type = tables.Column(
verbose_name='Type'
)
primary_ip = tables.Column(
order_by=('primary_ip4', 'primary_ip6'),
verbose_name='IP Address'
)
class Meta(BaseTable.Meta):
model = Device
fields = (
'name', 'status', 'tenant', 'site', 'location', 'rack', 'device_role', 'manufacturer', 'device_type',
'primary_ip',
)
exclude = ('id', )
orderable = False
class DeviceImportTable(BaseTable): class DeviceImportTable(BaseTable):
name = tables.TemplateColumn( name = tables.TemplateColumn(
template_code=DEVICE_LINK template_code=DEVICE_LINK

View File

@ -94,6 +94,14 @@ LOCATION_ELEVATIONS = """
</a> </a>
""" """
#
# Device table
#
DEVICE_ASSIGN_LINK = """
<a href="{% url 'dcim:device_edit' pk=record.pk %}?{% if request.GET.rack %}rack={{ request.GET.rack }}{% endif %}{% if request.GET.position %}&position={{ request.GET.position }}{% endif %}{% if request.GET.site %}&site={{ request.GET.site }}{% endif %}&location={{ object.location }}&face=front&return_url={{ request.GET.return_url }}">{{ record }}</a>
"""
# #
# Device component buttons # Device component buttons
# #

View File

@ -210,6 +210,7 @@ urlpatterns = [
# Devices # Devices
path('devices/', views.DeviceListView.as_view(), name='device_list'), path('devices/', views.DeviceListView.as_view(), name='device_list'),
path('devices/add/', views.DeviceEditView.as_view(), name='device_add'), path('devices/add/', views.DeviceEditView.as_view(), name='device_add'),
path('devices/assign/', views.DeviceAssignView.as_view(), name='device_assign'),
path('devices/import/', views.DeviceBulkImportView.as_view(), name='device_import'), path('devices/import/', views.DeviceBulkImportView.as_view(), name='device_import'),
path('devices/import/child-devices/', views.ChildDeviceBulkImportView.as_view(), name='device_import_child'), path('devices/import/child-devices/', views.ChildDeviceBulkImportView.as_view(), name='device_import_child'),
path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'), path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),

View File

@ -1463,6 +1463,46 @@ class DeviceEditView(generic.ObjectEditView):
model_form = forms.DeviceForm model_form = forms.DeviceForm
template_name = 'dcim/device_edit.html' template_name = 'dcim/device_edit.html'
class DeviceAssignView(generic.ObjectEditView):
"""
Search for Devices to be assigned to an Rack.
"""
queryset = Device.objects.all()
def dispatch(self, request, *args, **kwargs):
# Redirect user if an interface has not been provided
if 'rack' not in request.GET:
return redirect('ipam:ipaddress_add')
return super().dispatch(request, *args, **kwargs)
def get(self, request):
form = forms.DeviceAssignForm()
return render(request, 'dcim/device_assign.html', {
'form': form,
'return_url': request.GET.get('return_url', ''),
})
def post(self, request):
form = forms.DeviceAssignForm(request.POST)
table = None
if form.is_valid():
devices = self.queryset.prefetch_related('rack')
print(devices[0].rack.pk)
# Limit to 100 results
devices = filtersets.DeviceFilterSet(request.POST, devices).qs[:100]
table = tables.DeviceAssignTable(devices)
return render(request, 'dcim/device_assign.html', {
'form': form,
'table': table,
'return_url': request.GET.get('return_url'),
})
class DeviceDeleteView(generic.ObjectDeleteView): class DeviceDeleteView(generic.ObjectDeleteView):
queryset = Device.objects.all() queryset = Device.objects.all()

View File

@ -0,0 +1,48 @@
{% extends 'generic/object_edit.html' %}
{% load static %}
{% load form_helpers %}
{% load helpers %}
{% load render_table from django_tables2 %}
{% block title %}Assign a Device{% endblock title %}
{% block tabs %}
{% include 'dcim/inc/device_edit_header.html' with active_tab='assign' %}
{% endblock %}
{% block form %}
<form action="{% querystring request %}" method="post" class="form form-horizontal">
{% csrf_token %}
{% for field in form.hidden_fields %}
{{ field }}
{% endfor %}
<div class="row mb-3">
<div class="col col-md-8 offset-md-2">
<div class="field-group">
<h6>Select Device</h6>
{% render_field form.rack_id %}
{% render_field form.q %}
</div>
</div>
</div>
<div class="row mb-3">
<div class="col col-md-8 offset-md-2 text-end">
<a href="{{ return_url }}" class="btn btn-outline-danger">Cancel</a>
<button type="submit" class="btn btn-primary">Search</button>
</div>
</div>
</form>
{% if table %}
<div class="row mb-3">
<div class="col col-md-12">
<h3>Search Results</h3>
<div class="table-responsive">
{% render_table table 'inc/table.html' %}
</div>
</div>
</div>
{% endif %}
{% endblock form %}
{% block buttons %}
{% endblock buttons%}

View File

@ -1,6 +1,11 @@
{% extends 'generic/object_edit.html' %} {% extends 'generic/object_edit.html' %}
{% load form_helpers %} {% load form_helpers %}
{% block tabs %}
{% include 'dcim/inc/device_edit_header.html' with active_tab='add' %}
{% endblock %}
{% block form %} {% block form %}
{% render_errors form %} {% render_errors form %}

View File

@ -0,0 +1,22 @@
{% load helpers %}
<ul class="nav nav-tabs px-3">
<li class="nav-item">
<a
class="nav-link {% if active_tab == 'add' %}active{% endif %}"
href="{% url 'dcim:device_add' %}{% querystring request %}"
>
{% if obj.pk %}Edit{% else %}Create{% endif %}
</a>
</li>
{% if 'rack' in request.GET %}
<li class="nav-item">
<a
class="nav-link {% if active_tab == 'assign' %}active{% endif %}"
href="{% url 'dcim:device_assign' %}{% querystring request %}"
>
Assign Device
</a>
</li>
{% endif %}
</ul>