Skip to content

Commit 8250681

Browse files
committed
Closes #18147: Include device & VM interfaces in VRF related objects
1 parent 6b3b4b3 commit 8250681

File tree

3 files changed

+52
-18
lines changed

3 files changed

+52
-18
lines changed

netbox/ipam/views.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,26 @@ def get_extra_context(self, request, instance):
5353
)
5454
export_targets_table.configure(request)
5555

56+
related_models = self.get_related_models(
57+
request,
58+
instance,
59+
omit=(Interface, VMInterface),
60+
extra=(
61+
(
62+
Interface.objects.restrict(request.user, 'view').filter(vrf=instance),
63+
'vrf_id',
64+
_('Device Interfaces')
65+
),
66+
(
67+
VMInterface.objects.restrict(request.user, 'view').filter(vrf=instance),
68+
'vrf_id',
69+
_('VM Interfaces')
70+
),
71+
),
72+
)
73+
5674
return {
57-
'related_models': self.get_related_models(request, instance, omit=[Interface, VMInterface]),
75+
'related_models': related_models,
5876
'import_targets_table': import_targets_table,
5977
'export_targets_table': export_targets_table,
6078
}

netbox/templates/inc/panels/related_objects.html

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
<div class="card">
55
<h2 class="card-header">{% trans "Related Objects" %}</h2>
66
<ul class="list-group list-group-flush" role="presentation">
7-
{% for qs, filter_param in related_models %}
8-
{% with viewname=qs.model|validated_viewname:"list" %}
7+
{% for related_object_count in related_models %}
8+
{% with viewname=related_object_count.queryset.model|validated_viewname:"list" %}
99
{% if viewname is not None %}
10-
<a href="{% url viewname %}?{{ filter_param }}={{ object.pk }}" class="list-group-item list-group-item-action d-flex justify-content-between">
11-
{{ qs.model|meta:"verbose_name_plural"|bettertitle }}
12-
{% with count=qs.count %}
13-
{% if count %}
14-
<span class="badge text-bg-primary rounded-pill">{{ count }}</span>
15-
{% else %}
16-
<span class="badge text-bg-light rounded-pill">&mdash;</span>
17-
{% endif %}
18-
{% endwith %}
19-
</a>
10+
<a href="{% url viewname %}?{{ filter_param }}={{ object.pk }}" class="list-group-item list-group-item-action d-flex justify-content-between">
11+
{{ related_object_count.name }}
12+
{% with count=related_object_count.queryset.count %}
13+
{% if count %}
14+
<span class="badge text-bg-primary rounded-pill">{{ count }}</span>
15+
{% else %}
16+
<span class="badge text-bg-light rounded-pill">&mdash;</span>
17+
{% endif %}
18+
{% endwith %}
19+
</a>
2020
{% endif %}
2121
{% endwith %}
2222
{% empty %}

netbox/utilities/views.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from dataclasses import dataclass
12
from typing import Iterable
23

34
from django.conf import settings
45
from django.contrib.auth.mixins import AccessMixin
56
from django.core.exceptions import ImproperlyConfigured
7+
from django.db.models import QuerySet
68
from django.urls import reverse
79
from django.urls.exceptions import NoReverseMatch
810
from django.utils.translation import gettext_lazy as _
@@ -12,6 +14,7 @@
1214
from netbox.registry import registry
1315
from utilities.relations import get_related_models
1416
from utilities.request import safe_for_redirect
17+
from utilities.string import title
1518
from .permissions import resolve_permission
1619

1720
__all__ = (
@@ -177,8 +180,17 @@ class GetRelatedModelsMixin:
177180
"""
178181
Provides logic for collecting all related models for the currently viewed model.
179182
"""
183+
@dataclass
184+
class RelatedObjectCount:
185+
queryset: QuerySet
186+
filter_param: str
187+
label: str = ''
180188

181-
def get_related_models(self, request, instance, omit=[], extra=[]):
189+
@property
190+
def name(self):
191+
return self.label or title(_(self.queryset.model._meta.verbose_name_plural))
192+
193+
def get_related_models(self, request, instance, omit=None, extra=None):
182194
"""
183195
Get related models of the view's `queryset` model without those listed in `omit`. Will be sorted alphabetical.
184196
@@ -191,14 +203,15 @@ def get_related_models(self, request, instance, omit=[], extra=[]):
191203
extra: Add extra models to the list of automatically determined related models. Can be used to add indirect
192204
relationships.
193205
"""
206+
omit = omit or []
194207
model = self.queryset.model
195208
related = filter(
196209
lambda m: m[0] is not model and m[0] not in omit,
197210
get_related_models(model, False)
198211
)
199212

200213
related_models = [
201-
(
214+
self.RelatedObjectCount(
202215
model.objects.restrict(request.user, 'view').filter(**(
203216
{f'{field}__in': instance}
204217
if isinstance(instance, Iterable)
@@ -208,11 +221,14 @@ def get_related_models(self, request, instance, omit=[], extra=[]):
208221
)
209222
for model, field in related
210223
]
211-
related_models.extend(extra)
224+
if extra is not None:
225+
related_models.extend([
226+
self.RelatedObjectCount(*attrs) for attrs in extra
227+
])
212228

213229
return sorted(
214-
filter(lambda qs: qs[0].exists(), related_models),
215-
key=lambda qs: qs[0].model._meta.verbose_name.lower(),
230+
filter(lambda roc: roc.queryset.exists(), related_models),
231+
key=lambda roc: roc.name,
216232
)
217233

218234

0 commit comments

Comments
 (0)