From 85b10b59e4366de319e531c951be91b614717ae7 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 14 Dec 2021 16:38:25 -0500 Subject: [PATCH] Introduce child prefixes view for aggregates --- netbox/ipam/models/ip.py | 6 + netbox/ipam/urls.py | 1 + netbox/ipam/views.py | 45 +++---- netbox/templates/ipam/aggregate.html | 126 ++++++++---------- netbox/templates/ipam/aggregate/base.html | 23 ++++ netbox/templates/ipam/aggregate/prefixes.html | 36 +++++ 6 files changed, 140 insertions(+), 97 deletions(-) create mode 100644 netbox/templates/ipam/aggregate/base.html create mode 100644 netbox/templates/ipam/aggregate/prefixes.html diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index c361acd01..aeb71e70f 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -195,6 +195,12 @@ class Aggregate(PrimaryModel): return self.prefix.version return None + def get_child_prefixes(self): + """ + Return all Prefixes within this Aggregate + """ + return Prefix.objects.filter(prefix__net_contained=str(self.prefix)) + def get_utilization(self): """ Determine the prefix utilization of the aggregate and return it as a percentage. diff --git a/netbox/ipam/urls.py b/netbox/ipam/urls.py index 541acb3ac..e9bba8fa1 100644 --- a/netbox/ipam/urls.py +++ b/netbox/ipam/urls.py @@ -61,6 +61,7 @@ urlpatterns = [ path('aggregates/edit/', views.AggregateBulkEditView.as_view(), name='aggregate_bulk_edit'), path('aggregates/delete/', views.AggregateBulkDeleteView.as_view(), name='aggregate_bulk_delete'), path('aggregates//', views.AggregateView.as_view(), name='aggregate'), + path('aggregates//prefixes/', views.AggregatePrefixesView.as_view(), name='aggregate_prefixes'), path('aggregates//edit/', views.AggregateEditView.as_view(), name='aggregate_edit'), path('aggregates//delete/', views.AggregateDeleteView.as_view(), name='aggregate_delete'), path('aggregates//changelog/', ObjectChangeLogView.as_view(), name='aggregate_changelog', kwargs={'model': Aggregate}), diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 04bcdb480..a2942ea63 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -275,39 +275,32 @@ class AggregateListView(generic.ObjectListView): class AggregateView(generic.ObjectView): queryset = Aggregate.objects.all() - def get_extra_context(self, request, instance): - # Find all child prefixes contained in this aggregate - prefix_list = Prefix.objects.restrict(request.user, 'view').filter( - prefix__net_contained_or_equal=str(instance.prefix) - ).prefetch_related( - 'site', 'role' - ).order_by( - 'prefix' - ) - # Return List of requested Prefixes +class AggregatePrefixesView(generic.ObjectChildrenView): + queryset = Aggregate.objects.all() + child_model = Prefix + table = tables.PrefixTable + filterset = filtersets.PrefixFilterSet + template_name = 'ipam/aggregate/prefixes.html' + + def get_children(self, request, parent): + return Prefix.objects.restrict(request.user, 'view').filter( + prefix__net_contained_or_equal=str(parent.prefix) + ).prefetch_related('site', 'role', 'tenant', 'vlan') + + def prep_table_data(self, request, queryset, parent): + # Determine whether to show assigned prefixes, available prefixes, or both show_available = bool(request.GET.get('show_available', 'true') == 'true') show_assigned = bool(request.GET.get('show_assigned', 'true') == 'true') - child_prefixes = add_requested_prefixes(instance.prefix, prefix_list, show_available, show_assigned) - prefix_table = tables.PrefixTable(child_prefixes, exclude=('utilization',)) - if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): - prefix_table.columns.show('pk') - paginate_table(prefix_table, request) - - # Compile permissions list for rendering the object table - permissions = { - 'add': request.user.has_perm('ipam.add_prefix'), - 'change': request.user.has_perm('ipam.change_prefix'), - 'delete': request.user.has_perm('ipam.delete_prefix'), - } + return add_requested_prefixes(parent.prefix, queryset, show_available, show_assigned) + def get_extra_context(self, request, instance): return { - 'prefix_table': prefix_table, - 'permissions': permissions, 'bulk_querystring': f'within={instance.prefix}', - 'show_available': show_available, - 'show_assigned': show_assigned, + 'active_tab': 'prefixes', + 'show_available': bool(request.GET.get('show_available', 'true') == 'true'), + 'show_assigned': bool(request.GET.get('show_assigned', 'true') == 'true'), } diff --git a/netbox/templates/ipam/aggregate.html b/netbox/templates/ipam/aggregate.html index aca89a526..9f657c911 100644 --- a/netbox/templates/ipam/aggregate.html +++ b/netbox/templates/ipam/aggregate.html @@ -1,82 +1,66 @@ -{% extends 'generic/object.html' %} +{% extends 'ipam/aggregate/base.html' %} {% load buttons %} {% load helpers %} {% load plugins %} -{% block breadcrumbs %} - {{ block.super }} - -{% endblock %} - -{% block extra_controls %} - {% include 'ipam/inc/toggle_available.html' %} -{% endblock %} - {% block content %} -
-
-
-
- Aggregate -
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
FamilyIPv{{ object.family }}
RIR - {{ object.rir }} -
Utilization - {% utilization_graph object.get_utilization %} -
Tenant - {% if object.tenant %} - {% if prefix.object.group %} - {{ object.tenant.group }} / - {% endif %} - {{ object.tenant }} - {% else %} - None - {% endif %} -
Date Added{{ object.date_added|annotated_date|placeholder }}
Description{{ object.description|placeholder }}
-
+
+
+
+
Aggregate
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
FamilyIPv{{ object.family }}
RIR + {{ object.rir }} +
Utilization + {% utilization_graph object.get_utilization %} +
Tenant + {% if object.tenant %} + {% if prefix.object.group %} + {{ object.tenant.group }} / + {% endif %} + {{ object.tenant }} + {% else %} + None + {% endif %} +
Date Added{{ object.date_added|annotated_date|placeholder }}
Description{{ object.description|placeholder }}
- {% plugin_left_page object %} +
+ {% plugin_left_page object %}
- {% include 'inc/panels/custom_fields.html' %} - {% include 'inc/panels/tags.html' %} - {% plugin_right_page object %} + {% include 'inc/panels/custom_fields.html' %} + {% include 'inc/panels/tags.html' %} + {% plugin_right_page object %} +
+
+
+
+ {% plugin_full_width_page object %}
-
-
-
- {% plugin_full_width_page object %} -
-
-
-
- {% include 'utilities/obj_table.html' with table=prefix_table heading='Child Prefixes' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' %}
-
{% endblock %} diff --git a/netbox/templates/ipam/aggregate/base.html b/netbox/templates/ipam/aggregate/base.html new file mode 100644 index 000000000..09e17cf4f --- /dev/null +++ b/netbox/templates/ipam/aggregate/base.html @@ -0,0 +1,23 @@ +{% extends 'generic/object.html' %} +{% load buttons %} +{% load helpers %} + +{% block breadcrumbs %} + {{ block.super }} + +{% endblock %} + +{% block tab_items %} + + {% if perms.ipam.view_prefix %} + + {% endif %} +{% endblock %} diff --git a/netbox/templates/ipam/aggregate/prefixes.html b/netbox/templates/ipam/aggregate/prefixes.html new file mode 100644 index 000000000..22a74bd45 --- /dev/null +++ b/netbox/templates/ipam/aggregate/prefixes.html @@ -0,0 +1,36 @@ +{% extends 'ipam/aggregate/base.html' %} +{% load helpers %} + +{% block extra_controls %} + {% include 'ipam/inc/toggle_available.html' %} + {{ block.super }} +{% endblock %} + +{% block content %} +
+ {% csrf_token %} + {% include 'inc/table_controls_htmx.html' with table_modal="PrefixTable_config" %} + +
+
+ {% include 'htmx/table.html' %} +
+
+ +
+
+ {% if perms.ipam.change_prefix %} + + {% endif %} + {% if perms.ipam.delete_prefix %} + + {% endif %} +
+
+
+ {% table_config_form table %} +{% endblock %}