mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 01:06:11 -06:00
Allow racking of existing devices from rack view
This commit is contained in:
parent
c8f4a7c742
commit
b1f15de8f1
@ -25,6 +25,7 @@ __all__ = (
|
||||
'ConsolePortTemplateForm',
|
||||
'ConsoleServerPortForm',
|
||||
'ConsoleServerPortTemplateForm',
|
||||
'DeviceAssignForm',
|
||||
'DeviceBayForm',
|
||||
'DeviceBayTemplateForm',
|
||||
'DeviceForm',
|
||||
@ -40,9 +41,9 @@ __all__ = (
|
||||
'InventoryItemTemplateForm',
|
||||
'LocationForm',
|
||||
'ManufacturerForm',
|
||||
'ModuleForm',
|
||||
'ModuleBayForm',
|
||||
'ModuleBayTemplateForm',
|
||||
'ModuleForm',
|
||||
'ModuleTypeForm',
|
||||
'PlatformForm',
|
||||
'PopulateDeviceBayForm',
|
||||
@ -474,6 +475,18 @@ class PlatformForm(NetBoxModelForm):
|
||||
}
|
||||
|
||||
|
||||
class DeviceAssignForm(BootstrapMixin, forms.Form):
|
||||
q = forms.CharField(
|
||||
required=False,
|
||||
label=_('Search'),
|
||||
)
|
||||
show_racked_devices = forms.BooleanField(
|
||||
required=False,
|
||||
initial=False,
|
||||
label=_('Show Racked Devices?'),
|
||||
)
|
||||
|
||||
|
||||
class DeviceForm(TenancyForm, NetBoxModelForm):
|
||||
region = DynamicModelChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
|
@ -12,6 +12,7 @@ __all__ = (
|
||||
'CableTerminationTable',
|
||||
'ConsolePortTable',
|
||||
'ConsoleServerPortTable',
|
||||
'DeviceAssignTable',
|
||||
'DeviceBayTable',
|
||||
'DeviceConsolePortTable',
|
||||
'DeviceConsoleServerPortTable',
|
||||
@ -21,8 +22,8 @@ __all__ = (
|
||||
'DeviceInterfaceTable',
|
||||
'DeviceInventoryItemTable',
|
||||
'DeviceModuleBayTable',
|
||||
'DevicePowerPortTable',
|
||||
'DevicePowerOutletTable',
|
||||
'DevicePowerPortTable',
|
||||
'DeviceRearPortTable',
|
||||
'DeviceRoleTable',
|
||||
'DeviceTable',
|
||||
@ -219,6 +220,20 @@ class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
)
|
||||
|
||||
|
||||
class DeviceAssignTable(NetBoxTable):
|
||||
device = tables.TemplateColumn(
|
||||
template_code=DEVICE_ASSIGN_LINK,
|
||||
verbose_name='Device'
|
||||
)
|
||||
status = columns.ChoiceFieldColumn()
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = models.Device
|
||||
fields = ('device', 'status', 'device_role', 'site', 'location', 'rack', 'position')
|
||||
exclude = ('id',)
|
||||
orderable = False
|
||||
|
||||
|
||||
class DeviceImportTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.TemplateColumn(
|
||||
template_code=DEVICE_LINK,
|
||||
|
@ -24,6 +24,10 @@ DEVICE_LINK = """
|
||||
{{ value|default:'<span class="badge bg-info">Unnamed device</span>' }}
|
||||
"""
|
||||
|
||||
DEVICE_ASSIGN_LINK = """
|
||||
<a href="{% url 'dcim:device_edit' pk=record.pk %}?{% if request.GET.rack %}rack={{ request.GET.rack }}&face={{ request.GET.face }}&position={{ request.GET.position }}{% endif %}&return_url={{ request.GET.return_url }}">{{ record }}</a>
|
||||
"""
|
||||
|
||||
DEVICEBAY_STATUS = """
|
||||
{% if record.installed_device_id %}
|
||||
<span class="badge bg-{{ record.installed_device.get_status_color }}">
|
||||
|
@ -176,6 +176,7 @@ urlpatterns = [
|
||||
# Devices
|
||||
path('devices/', views.DeviceListView.as_view(), name='device_list'),
|
||||
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/child-devices/', views.ChildDeviceBulkImportView.as_view(), name='device_import_child'),
|
||||
path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),
|
||||
|
@ -1880,6 +1880,49 @@ class DeviceDeleteView(generic.ObjectDeleteView):
|
||||
queryset = Device.objects.all()
|
||||
|
||||
|
||||
class DeviceAssignView(generic.ObjectView):
|
||||
"""
|
||||
Search for Devices to be assigned to a rack.
|
||||
"""
|
||||
queryset = Device.objects.all()
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
|
||||
# Redirect user if a rack has not been provided
|
||||
if 'rack' not in request.GET:
|
||||
return redirect('dcim:device_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():
|
||||
rack = Rack.objects.get(pk=request.GET['rack'])
|
||||
# Only get devices belonging to the same site as rack
|
||||
devices = self.queryset.filter(site=rack.site)
|
||||
if not form.cleaned_data['show_racked_devices']:
|
||||
devices = devices.exclude(rack__isnull=False)
|
||||
# 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'),
|
||||
})
|
||||
|
||||
|
||||
@register_model_view(Device, 'consoleports', path='console-ports')
|
||||
class DeviceConsolePortsView(DeviceComponentsView):
|
||||
child_model = ConsolePort
|
||||
|
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.q %}
|
||||
{% render_field form.show_racked_devices %}
|
||||
</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,10 @@
|
||||
{% extends 'generic/object_edit.html' %}
|
||||
{% load form_helpers %}
|
||||
|
||||
{% block tabs %}
|
||||
{% include 'dcim/inc/device_edit_header.html' with active_tab='add' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block 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