Преглед изворни кода

Closes #18147: Include device & VM interfaces in VRF related objects (#20158)

Jeremy Stretch пре 5 месеци
родитељ
комит
66140fc017
3 измењених фајлова са 52 додато и 18 уклоњено
  1. 19 1
      netbox/ipam/views.py
  2. 12 12
      netbox/templates/inc/panels/related_objects.html
  3. 21 5
      netbox/utilities/views.py

+ 19 - 1
netbox/ipam/views.py

@@ -53,8 +53,26 @@ class VRFView(GetRelatedModelsMixin, generic.ObjectView):
         )
         )
         export_targets_table.configure(request)
         export_targets_table.configure(request)
 
 
+        related_models = self.get_related_models(
+            request,
+            instance,
+            omit=(Interface, VMInterface),
+            extra=(
+                (
+                    Interface.objects.restrict(request.user, 'view').filter(vrf=instance),
+                    'vrf_id',
+                    _('Device Interfaces')
+                ),
+                (
+                    VMInterface.objects.restrict(request.user, 'view').filter(vrf=instance),
+                    'vrf_id',
+                    _('VM Interfaces')
+                ),
+            ),
+        )
+
         return {
         return {
-            'related_models': self.get_related_models(request, instance, omit=[Interface, VMInterface]),
+            'related_models': related_models,
             'import_targets_table': import_targets_table,
             'import_targets_table': import_targets_table,
             'export_targets_table': export_targets_table,
             'export_targets_table': export_targets_table,
         }
         }

+ 12 - 12
netbox/templates/inc/panels/related_objects.html

@@ -4,19 +4,19 @@
 <div class="card">
 <div class="card">
   <h2 class="card-header">{% trans "Related Objects" %}</h2>
   <h2 class="card-header">{% trans "Related Objects" %}</h2>
   <ul class="list-group list-group-flush" role="presentation">
   <ul class="list-group list-group-flush" role="presentation">
-    {% for qs, filter_param in related_models %}
-      {% with viewname=qs.model|validated_viewname:"list" %}
+    {% for related_object_count in related_models %}
+      {% with viewname=related_object_count.queryset.model|validated_viewname:"list" %}
         {% if viewname is not None %}
         {% if viewname is not None %}
-        <a href="{% url viewname %}?{{ filter_param }}={{ object.pk }}" class="list-group-item list-group-item-action d-flex justify-content-between">
-          {{ qs.model|meta:"verbose_name_plural"|bettertitle }}
-          {% with count=qs.count %}
-            {% if count %}
-              <span class="badge text-bg-primary rounded-pill">{{ count }}</span>
-            {% else %}
-              <span class="badge text-bg-light rounded-pill">&mdash;</span>
-            {% endif %}
-          {% endwith %}
-        </a>
+          <a href="{% url viewname %}?{{ related_object_count.filter_param }}={{ object.pk }}" class="list-group-item list-group-item-action d-flex justify-content-between">
+            {{ related_object_count.name }}
+            {% with count=related_object_count.queryset.count %}
+              {% if count %}
+                <span class="badge text-bg-primary rounded-pill">{{ count }}</span>
+              {% else %}
+                <span class="badge text-bg-light rounded-pill">&mdash;</span>
+              {% endif %}
+            {% endwith %}
+          </a>
         {% endif %}
         {% endif %}
       {% endwith %}
       {% endwith %}
     {% empty %}
     {% empty %}

+ 21 - 5
netbox/utilities/views.py

@@ -1,8 +1,10 @@
+from dataclasses import dataclass
 from typing import Iterable
 from typing import Iterable
 
 
 from django.conf import settings
 from django.conf import settings
 from django.contrib.auth.mixins import AccessMixin
 from django.contrib.auth.mixins import AccessMixin
 from django.core.exceptions import ImproperlyConfigured
 from django.core.exceptions import ImproperlyConfigured
+from django.db.models import QuerySet
 from django.urls import reverse
 from django.urls import reverse
 from django.urls.exceptions import NoReverseMatch
 from django.urls.exceptions import NoReverseMatch
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import gettext_lazy as _
@@ -12,6 +14,7 @@ from netbox.plugins import PluginConfig
 from netbox.registry import registry
 from netbox.registry import registry
 from utilities.relations import get_related_models
 from utilities.relations import get_related_models
 from utilities.request import safe_for_redirect
 from utilities.request import safe_for_redirect
+from utilities.string import title
 from .permissions import resolve_permission
 from .permissions import resolve_permission
 
 
 __all__ = (
 __all__ = (
@@ -177,8 +180,17 @@ class GetRelatedModelsMixin:
     """
     """
     Provides logic for collecting all related models for the currently viewed model.
     Provides logic for collecting all related models for the currently viewed model.
     """
     """
+    @dataclass
+    class RelatedObjectCount:
+        queryset: QuerySet
+        filter_param: str
+        label: str = ''
 
 
-    def get_related_models(self, request, instance, omit=[], extra=[]):
+        @property
+        def name(self):
+            return self.label or title(_(self.queryset.model._meta.verbose_name_plural))
+
+    def get_related_models(self, request, instance, omit=None, extra=None):
         """
         """
         Get related models of the view's `queryset` model without those listed in `omit`. Will be sorted alphabetical.
         Get related models of the view's `queryset` model without those listed in `omit`. Will be sorted alphabetical.
 
 
@@ -191,6 +203,7 @@ class GetRelatedModelsMixin:
             extra: Add extra models to the list of automatically determined related models. Can be used to add indirect
             extra: Add extra models to the list of automatically determined related models. Can be used to add indirect
                 relationships.
                 relationships.
         """
         """
+        omit = omit or []
         model = self.queryset.model
         model = self.queryset.model
         related = filter(
         related = filter(
             lambda m: m[0] is not model and m[0] not in omit,
             lambda m: m[0] is not model and m[0] not in omit,
@@ -198,7 +211,7 @@ class GetRelatedModelsMixin:
         )
         )
 
 
         related_models = [
         related_models = [
-            (
+            self.RelatedObjectCount(
                 model.objects.restrict(request.user, 'view').filter(**(
                 model.objects.restrict(request.user, 'view').filter(**(
                     {f'{field}__in': instance}
                     {f'{field}__in': instance}
                     if isinstance(instance, Iterable)
                     if isinstance(instance, Iterable)
@@ -208,11 +221,14 @@ class GetRelatedModelsMixin:
             )
             )
             for model, field in related
             for model, field in related
         ]
         ]
-        related_models.extend(extra)
+        if extra is not None:
+            related_models.extend([
+                self.RelatedObjectCount(*attrs) for attrs in extra
+            ])
 
 
         return sorted(
         return sorted(
-            filter(lambda qs: qs[0].exists(), related_models),
-            key=lambda qs: qs[0].model._meta.verbose_name.lower(),
+            filter(lambda roc: roc.queryset.exists(), related_models),
+            key=lambda roc: roc.name,
         )
         )