mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-16 12:12:53 -06:00
Introduce child prefixes view for aggregates
This commit is contained in:
parent
9a53c22833
commit
85b10b59e4
@ -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.
|
||||
|
@ -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/<int:pk>/', views.AggregateView.as_view(), name='aggregate'),
|
||||
path('aggregates/<int:pk>/prefixes/', views.AggregatePrefixesView.as_view(), name='aggregate_prefixes'),
|
||||
path('aggregates/<int:pk>/edit/', views.AggregateEditView.as_view(), name='aggregate_edit'),
|
||||
path('aggregates/<int:pk>/delete/', views.AggregateDeleteView.as_view(), name='aggregate_delete'),
|
||||
path('aggregates/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='aggregate_changelog', kwargs={'model': Aggregate}),
|
||||
|
@ -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'),
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,82 +1,66 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% extends 'ipam/aggregate/base.html' %}
|
||||
{% load buttons %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ block.super }}
|
||||
<li class="breadcrumb-item"><a href="{% url 'ipam:aggregate_list' %}?rir_id={{ object.rir.pk }}">{{ object.rir }}</a></li>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_controls %}
|
||||
{% include 'ipam/inc/toggle_available.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col col-md-6">
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Aggregate
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<td>Family</td>
|
||||
<td>IPv{{ object.family }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RIR</td>
|
||||
<td>
|
||||
<a href="{% url 'ipam:aggregate_list' %}?rir={{ object.rir.slug }}">{{ object.rir }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Utilization</td>
|
||||
<td>
|
||||
{% utilization_graph object.get_utilization %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tenant</td>
|
||||
<td>
|
||||
{% if object.tenant %}
|
||||
{% if prefix.object.group %}
|
||||
<a href="{{ object.tenant.group.get_absolute_url }}">{{ object.tenant.group }}</a> /
|
||||
{% endif %}
|
||||
<a href="{{ object.tenant.get_absolute_url }}">{{ object.tenant }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date Added</td>
|
||||
<td>{{ object.date_added|annotated_date|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col col-md-6">
|
||||
<div class="card">
|
||||
<h5 class="card-header">Aggregate</h5>
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<td>Family</td>
|
||||
<td>IPv{{ object.family }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RIR</td>
|
||||
<td>
|
||||
<a href="{% url 'ipam:aggregate_list' %}?rir={{ object.rir.slug }}">{{ object.rir }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Utilization</td>
|
||||
<td>
|
||||
{% utilization_graph object.get_utilization %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tenant</td>
|
||||
<td>
|
||||
{% if object.tenant %}
|
||||
{% if prefix.object.group %}
|
||||
<a href="{{ object.tenant.group.get_absolute_url }}">{{ object.tenant.group }}</a> /
|
||||
{% endif %}
|
||||
<a href="{{ object.tenant.get_absolute_url }}">{{ object.tenant }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date Added</td>
|
||||
<td>{{ object.date_added|annotated_date|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col col-md-6">
|
||||
{% 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 %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
{% plugin_full_width_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
{% plugin_full_width_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
{% 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' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
23
netbox/templates/ipam/aggregate/base.html
Normal file
23
netbox/templates/ipam/aggregate/base.html
Normal file
@ -0,0 +1,23 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load buttons %}
|
||||
{% load helpers %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ block.super }}
|
||||
<li class="breadcrumb-item"><a href="{% url 'ipam:aggregate_list' %}?rir_id={{ object.rir.pk }}">{{ object.rir }}</a></li>
|
||||
{% endblock %}
|
||||
|
||||
{% block tab_items %}
|
||||
<li role="presentation" class="nav-item">
|
||||
<a class="nav-link{% if not active_tab %} active{% endif %}" href="{{ object.get_absolute_url }}">
|
||||
Aggregate
|
||||
</a>
|
||||
</li>
|
||||
{% if perms.ipam.view_prefix %}
|
||||
<li role="presentation" class="nav-item">
|
||||
<a class="nav-link{% if active_tab == 'prefixes' %} active{% endif %}" href="{% url 'ipam:aggregate_prefixes' pk=object.pk %}">
|
||||
Prefixes {% badge object.get_child_prefixes.count %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endblock %}
|
36
netbox/templates/ipam/aggregate/prefixes.html
Normal file
36
netbox/templates/ipam/aggregate/prefixes.html
Normal file
@ -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 %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{% include 'inc/table_controls_htmx.html' with table_modal="PrefixTable_config" %}
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body" id="object_list">
|
||||
{% include 'htmx/table.html' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="noprint bulk-buttons">
|
||||
<div class="bulk-button-group">
|
||||
{% if perms.ipam.change_prefix %}
|
||||
<button type="submit" name="_edit" formaction="{% url 'ipam:prefix_bulk_edit' %}?return_url={% url 'ipam:prefix_prefixes' pk=object.pk %}" class="btn btn-warning btn-sm">
|
||||
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if perms.ipam.delete_prefix %}
|
||||
<button type="submit" name="_delete" formaction="{% url 'ipam:prefix_bulk_delete' %}?return_url={% url 'ipam:prefix_prefixes' pk=object.pk %}" class="btn btn-danger btn-sm">
|
||||
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% table_config_form table %}
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user