Skip to content

Commit ef9cafe

Browse files
committed
adds generic tab view template #12110
1 parent 88562d7 commit ef9cafe

30 files changed

+250
-1003
lines changed

netbox/ipam/views.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ class ASNRangeASNsView(generic.ObjectChildrenView):
216216
child_model = ASN
217217
table = tables.ASNTable
218218
filterset = filtersets.ASNFilterSet
219-
template_name = 'ipam/asnrange/asns.html'
220219
tab = ViewTab(
221220
label=_('ASNs'),
222221
badge=lambda x: x.get_child_asns().count(),
@@ -367,7 +366,9 @@ def prep_table_data(self, request, queryset, parent):
367366
return add_requested_prefixes(parent.prefix, queryset, show_available, show_assigned)
368367

369368
def get_extra_context(self, request, instance):
369+
context = super().get_extra_context(request, instance)
370370
return {
371+
**context,
371372
'bulk_querystring': f'within={instance.prefix}',
372373
'first_available_prefix': instance.get_first_available_prefix(),
373374
'show_available': bool(request.GET.get('show_available', 'true') == 'true'),
@@ -554,7 +555,9 @@ def prep_table_data(self, request, queryset, parent):
554555
return add_requested_prefixes(parent.prefix, queryset, show_available, show_assigned)
555556

556557
def get_extra_context(self, request, instance):
558+
context = super().get_extra_context(request, instance)
557559
return {
560+
**context,
558561
'bulk_querystring': f"vrf_id={instance.vrf.pk if instance.vrf else '0'}&within={instance.prefix}",
559562
'first_available_prefix': instance.get_first_available_prefix(),
560563
'show_available': bool(request.GET.get('show_available', 'true') == 'true'),
@@ -582,7 +585,9 @@ def get_children(self, request, parent):
582585
)
583586

584587
def get_extra_context(self, request, instance):
588+
context = super().get_extra_context(request, instance)
585589
return {
590+
**context,
586591
'bulk_querystring': f"vrf_id={instance.vrf.pk if instance.vrf else '0'}&parent={instance.prefix}",
587592
'first_available_ip': instance.get_first_available_ip(),
588593
}
@@ -611,7 +616,9 @@ def prep_table_data(self, request, queryset, parent):
611616
return queryset
612617

613618
def get_extra_context(self, request, instance):
619+
context = super().get_extra_context(request, instance)
614620
return {
621+
**context,
615622
'bulk_querystring': f"vrf_id={instance.vrf.pk if instance.vrf else '0'}&parent={instance.prefix}",
616623
'first_available_ip': instance.get_first_available_ip(),
617624
}
@@ -816,7 +823,6 @@ def post(self, request):
816823
table = None
817824

818825
if form.is_valid():
819-
820826
addresses = self.queryset.prefetch_related('vrf', 'tenant')
821827
# Limit to 100 results
822828
addresses = filtersets.IPAddressFilterSet(request.POST, addresses).qs[:100]
@@ -866,7 +872,6 @@ class IPAddressRelatedIPsView(generic.ObjectChildrenView):
866872
child_model = IPAddress
867873
table = tables.IPAddressTable
868874
filterset = filtersets.IPAddressFilterSet
869-
template_name = 'ipam/ipaddress/ip_addresses.html'
870875
tab = ViewTab(
871876
label=_('Related IPs'),
872877
badge=lambda x: x.get_related_ips().count(),
@@ -963,7 +968,6 @@ class FHRPGroupView(generic.ObjectView):
963968
queryset = FHRPGroup.objects.all()
964969

965970
def get_extra_context(self, request, instance):
966-
967971
# Get assigned interfaces
968972
members_table = tables.FHRPGroupAssignmentTable(
969973
data=FHRPGroupAssignment.objects.restrict(request.user, 'view').filter(group=instance),
@@ -1077,7 +1081,6 @@ class VLANInterfacesView(generic.ObjectChildrenView):
10771081
child_model = Interface
10781082
table = tables.VLANDevicesTable
10791083
filterset = InterfaceFilterSet
1080-
template_name = 'ipam/vlan/interfaces.html'
10811084
tab = ViewTab(
10821085
label=_('Device Interfaces'),
10831086
badge=lambda x: x.get_interfaces().count(),
@@ -1095,7 +1098,6 @@ class VLANVMInterfacesView(generic.ObjectChildrenView):
10951098
child_model = VMInterface
10961099
table = tables.VLANVirtualMachinesTable
10971100
filterset = VMInterfaceFilterSet
1098-
template_name = 'ipam/vlan/vminterfaces.html'
10991101
tab = ViewTab(
11001102
label=_('VM Interfaces'),
11011103
badge=lambda x: x.get_vminterfaces().count(),

netbox/netbox/views/generic/object_views.py

+24
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.db.models import ProtectedError
77
from django.shortcuts import redirect, render
88
from django.urls import reverse
9+
from django.urls.exceptions import NoReverseMatch
910
from django.utils.html import escape
1011
from django.utils.safestring import mark_safe
1112

@@ -90,6 +91,7 @@ class ObjectChildrenView(ObjectView, ActionsMixin, TableMixin):
9091
child_model = None
9192
table = None
9293
filterset = None
94+
template_name = 'inc/tab_view.html'
9395

9496
def get_children(self, request, parent):
9597
"""
@@ -112,6 +114,28 @@ def prep_table_data(self, request, queryset, parent):
112114
"""
113115
return queryset
114116

117+
def get_extra_context(self, request, instance):
118+
context = super().get_extra_context(request, instance)
119+
120+
return_url = '?return_url=' + request.get_full_path()
121+
bulk_edit_url = reverse(f'{self.child_model._meta.app_label}:{self.child_model._meta.model_name}_bulk_edit') + return_url
122+
bulk_delete_url = reverse(f'{self.child_model._meta.app_label}:{self.child_model._meta.model_name}_bulk_delete') + return_url
123+
124+
try:
125+
bulk_rename_url = reverse(
126+
f'{self.child_model._meta.app_label}:{self.child_model._meta.model_name}_bulk_rename') + return_url
127+
except NoReverseMatch:
128+
bulk_rename_url = None
129+
130+
context.update({
131+
'base_template': f'{instance._meta.app_label}/{instance._meta.model_name}.html',
132+
'table_config': f'{self.table.__name__}_config',
133+
'bulk_edit_url': bulk_edit_url,
134+
'bulk_delete_url': bulk_delete_url,
135+
'bulk_rename_url': bulk_rename_url,
136+
})
137+
return context
138+
115139
#
116140
# Request handlers
117141
#
+17-52
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,22 @@
1-
{% extends 'dcim/device/base.html' %}
2-
{% load render_table from django_tables2 %}
3-
{% load helpers %}
4-
{% load static %}
1+
{% extends 'inc/tab_view.html' %}
52

6-
{% block content %}
7-
{% include 'inc/table_controls_htmx.html' with table_modal="DeviceConsolePortTable_config" %}
8-
9-
<form method="post">
10-
{% csrf_token %}
11-
12-
<div class="card">
13-
<div class="card-body htmx-container table-responsive" id="object_list">
14-
{% include 'htmx/table.html' %}
15-
</div>
16-
</div>
17-
18-
<div class="noprint bulk-buttons">
19-
<div class="bulk-button-group">
20-
{% if 'bulk_edit' in actions %}
21-
<div class="btn-group" role="group">
22-
<button type="submit" name="_edit" formaction="{% url 'dcim:consoleport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-warning btn-sm">
23-
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
24-
</button>
25-
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleport_bulk_rename' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
26-
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
27-
</button>
28-
</div>
29-
{% endif %}
30-
<div class="btn-group" role="group">
31-
{% if 'bulk_delete' in actions %}
32-
<button type="submit" name="_delete" formaction="{% url 'dcim:consoleport_bulk_delete' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-danger btn-sm">
33-
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
34-
</button>
35-
{% endif %}
36-
{% if 'bulk_edit' in actions %}
37-
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleport_bulk_disconnect' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
38-
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
39-
</button>
40-
{% endif %}
41-
</div>
42-
</div>
43-
{% if perms.dcim.add_consoleport %}
3+
{% block extra_contols_bottom %}
4+
{% if perms.dcim.add_consoleserverport %}
445
<div class="bulk-button-group">
45-
<a href="{% url 'dcim:consoleport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-sm btn-primary">
46-
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Console Port
47-
</a>
6+
<a href="{% url 'dcim:consoleserverport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}"
7+
class="btn btn-primary btn-sm">
8+
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Console Server Ports
9+
</a>
4810
</div>
49-
{% endif %}
50-
</div>
51-
</form>
11+
{% endif %}
5212
{% endblock %}
5313

54-
{% block modals %}
55-
{{ block.super }}
56-
{% table_config_form table %}
57-
{% endblock modals %}
14+
{% block bulk_delete_control %}
15+
{% if 'bulk_edit' in actions %}
16+
<button type="submit" name="_disconnect"
17+
formaction="{% url 'dcim:consoleserverport_bulk_disconnect' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}"
18+
class="btn btn-outline-danger btn-sm">
19+
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
20+
</button>
21+
{% endif %}
22+
{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,22 @@
1-
{% extends 'dcim/device/base.html' %}
2-
{% load render_table from django_tables2 %}
3-
{% load helpers %}
4-
{% load static %}
1+
{% extends 'inc/tab_view.html' %}
52

6-
{% block content %}
7-
{% include 'inc/table_controls_htmx.html' with table_modal="DeviceConsoleServerPortTable_config" %}
8-
9-
<form method="post">
10-
{% csrf_token %}
11-
12-
<div class="card">
13-
<div class="card-body htmx-container table-responsive" id="object_list">
14-
{% include 'htmx/table.html' %}
15-
</div>
16-
</div>
3+
{% block bulk_delete_control %}
4+
{% if 'bulk_edit' in actions %}
5+
<button type="submit" name="_disconnect"
6+
formaction="{% url 'dcim:consoleserverport_bulk_disconnect' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}"
7+
class="btn btn-outline-danger btn-sm">
8+
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
9+
</button>
10+
{% endif %}
11+
{% endblock %}
1712

18-
<div class="noprint bulk-buttons">
19-
<div class="bulk-button-group">
20-
{% if 'bulk_edit' in actions %}
21-
<div class="btn-group" role="group">
22-
<button type="submit" name="_edit" formaction="{% url 'dcim:consoleserverport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-warning btn-sm">
23-
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
24-
</button>
25-
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleserverport_bulk_rename' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
26-
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
27-
</button>
28-
</div>
29-
{% endif %}
30-
<div class="btn-group" role="group">
31-
{% if 'bulk_delete' in actions %}
32-
<button type="submit" formaction="{% url 'dcim:consoleserverport_bulk_delete' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-danger btn-sm">
33-
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
34-
</button>
35-
{% endif %}
36-
{% if 'bulk_edit' in actions %}
37-
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleserverport_bulk_disconnect' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
38-
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
39-
</button>
40-
{% endif %}
41-
</div>
42-
</div>
43-
{% if perms.dcim.add_consoleserverport %}
13+
{% block extra_contols_bottom %}
14+
{% if perms.dcim.add_consoleserverport %}
4415
<div class="bulk-button-group">
45-
<a href="{% url 'dcim:consoleserverport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-primary btn-sm">
46-
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Console Server Ports
47-
</a>
16+
<a href="{% url 'dcim:consoleserverport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}"
17+
class="btn btn-primary btn-sm">
18+
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Console Server Ports
19+
</a>
4820
</div>
49-
{% endif %}
50-
</div>
51-
</form>
52-
{% endblock %}
53-
54-
{% block modals %}
55-
{{ block.super }}
56-
{% table_config_form table %}
57-
{% endblock modals %}
21+
{% endif %}
22+
{% endblock %}
+8-46
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,12 @@
1-
{% extends 'dcim/device/base.html' %}
2-
{% load render_table from django_tables2 %}
3-
{% load helpers %}
4-
{% load static %}
1+
{% extends 'inc/tab_view.html' %}
52

6-
{% block content %}
7-
{% include 'inc/table_controls_htmx.html' with table_modal="DeviceDeviceBayTable_config" %}
8-
9-
<form method="post">
10-
{% csrf_token %}
11-
12-
<div class="card">
13-
<div class="card-body htmx-container table-responsive" id="object_list">
14-
{% include 'htmx/table.html' %}
15-
</div>
16-
</div>
17-
18-
<div class="noprint bulk-buttons">
19-
<div class="bulk-button-group">
20-
{% if 'bulk_edit' in actions %}
21-
<div class="btn-group" role="group">
22-
<button type="submit" name="_edit" formaction="{% url 'dcim:devicebay_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_devicebays' pk=object.pk %}" class="btn btn-warning btn-sm">
23-
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
24-
</button>
25-
<button type="submit" name="_rename" formaction="{% url 'dcim:devicebay_bulk_rename' %}?return_url={% url 'dcim:device_devicebays' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
26-
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
27-
</button>
28-
</div>
29-
{% endif %}
30-
{% if 'bulk_delete' in actions %}
31-
<button type="submit" name="_delete" formaction="{% url 'dcim:devicebay_bulk_delete' %}?return_url={% url 'dcim:device_devicebays' pk=object.pk %}" class="btn btn-danger btn-sm">
32-
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
33-
</button>
34-
{% endif %}
35-
</div>
36-
{% if perms.dcim.add_devicebay %}
3+
{% block extra_contols_bottom %}
4+
{% if perms.dcim.add_devicebay %}
375
<div class="bulk-button-group">
38-
<a href="{% url 'dcim:devicebay_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_devicebays' pk=object.pk %}" class="btn btn-primary btn-sm">
39-
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Device Bays
40-
</a>
6+
<a href="{% url 'dcim:devicebay_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_devicebays' pk=object.pk %}"
7+
class="btn btn-primary btn-sm">
8+
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Device Bays
9+
</a>
4110
</div>
42-
{% endif %}
43-
</div>
44-
</form>
11+
{% endif %}
4512
{% endblock %}
46-
47-
{% block modals %}
48-
{{ block.super }}
49-
{% table_config_form table %}
50-
{% endblock modals %}

0 commit comments

Comments
 (0)