mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-17 13:08:16 -06:00
implement assign device for rack
This commit is contained in:
parent
1add5accf2
commit
1a817619c7
@ -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(),
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
#
|
#
|
||||||
|
@ -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'),
|
||||||
|
@ -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()
|
||||||
|
48
netbox/templates/dcim/device_assign.html
Normal file
48
netbox/templates/dcim/device_assign.html
Normal 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%}
|
@ -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 %}
|
||||||
|
|
||||||
|
22
netbox/templates/dcim/inc/device_edit_header.html
Normal file
22
netbox/templates/dcim/inc/device_edit_header.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user