diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py index 45084a339..f5129e5b8 100644 --- a/netbox/circuits/views.py +++ b/netbox/circuits/views.py @@ -150,17 +150,19 @@ class ProviderNetworkListView(generic.ObjectListView): class ProviderNetworkView(GetRelatedModelsMixin, generic.ObjectView): queryset = ProviderNetwork.objects.all() - def get_extra_related_models(self, request, instance): - return ( - ( - Circuit.objects.restrict(request.user, 'view').filter(terminations__provider_network=instance), - 'provider_network_id', - ), - ) - def get_extra_context(self, request, instance): return { - 'related_models': self.get_related_models(request, instance, [CircuitTermination]), + 'related_models': self.get_related_models( + request, + instance, + [CircuitTermination], + ( + ( + Circuit.objects.restrict(request.user, 'view').filter(terminations__provider_network=instance), + 'provider_network_id', + ), + ), + ), } diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 4f5bd6959..ab8e350ca 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -229,17 +229,18 @@ class RegionListView(generic.ObjectListView): class RegionView(GetRelatedModelsMixin, generic.ObjectView): queryset = Region.objects.all() - def get_extra_related_models(self, request, regions): - return ( - (Location.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'), - (Rack.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'), - ) - def get_extra_context(self, request, instance): regions = instance.get_descendants(include_self=True) return { - 'related_models': self.get_related_models(request, regions), + 'related_models': self.get_related_models( + request, + regions, + extra=( + (Location.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'), + (Rack.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'), + ), + ), } @@ -310,17 +311,18 @@ class SiteGroupListView(generic.ObjectListView): class SiteGroupView(GetRelatedModelsMixin, generic.ObjectView): queryset = SiteGroup.objects.all() - def get_extra_related_models(self, request, groups): - return ( - (Location.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'), - (Rack.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'), - ) - def get_extra_context(self, request, instance): groups = instance.get_descendants(include_self=True) return { - 'related_models': self.get_related_models(request, groups), + 'related_models': self.get_related_models( + request, + groups, + extra=( + (Location.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'), + (Rack.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'), + ), + ), } @@ -385,18 +387,20 @@ class SiteListView(generic.ObjectListView): class SiteView(GetRelatedModelsMixin, generic.ObjectView): queryset = Site.objects.prefetch_related('tenant__group') - def get_extra_related_models(self, request, instance): - return ( - (VLANGroup.objects.restrict(request.user, 'view').filter( - scope_type=ContentType.objects.get_for_model(Site), - scope_id=instance.pk - ), 'site'), - (Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct(), 'site_id'), - ) - def get_extra_context(self, request, instance): return { - 'related_models': self.get_related_models(request, instance, [CableTermination, CircuitTermination]), + 'related_models': self.get_related_models( + request, + instance, + [CableTermination, CircuitTermination], + ( + (VLANGroup.objects.restrict(request.user, 'view').filter( + scope_type=ContentType.objects.get_for_model(Site), + scope_id=instance.pk + ), 'site'), + (Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct(), 'site_id'), + ), + ), } @@ -3598,14 +3602,15 @@ class VirtualDeviceContextListView(generic.ObjectListView): class VirtualDeviceContextView(GetRelatedModelsMixin, generic.ObjectView): queryset = VirtualDeviceContext.objects.all() - def get_extra_related_models(self, request, instance): - return ( - (Interface.objects.restrict(request.user, 'view').filter(vdcs__in=[instance]), 'vdc_id'), - ) - def get_extra_context(self, request, instance): return { - 'related_models': self.get_related_models(request, instance), + 'related_models': self.get_related_models( + request, + instance, + extra=( + (Interface.objects.restrict(request.user, 'view').filter(vdcs__in=[instance]), 'vdc_id'), + ), + ), } diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 95df9020a..75c48b01f 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -151,14 +151,7 @@ class GetRelatedModelsMixin: Provides logic for collecting all related models for the currently viewed model. """ - def get_extra_related_models(self, request, instance): - """ - Get extra related models for `instance`, which extend `get_related_models`. Can be used to implement custom - lookups for nested and non-direct relationships. - """ - return [] - - def get_related_models(self, request, instance, omit=[]): + def get_related_models(self, request, instance, omit=[], extra=[]): """ Get related models of the view's `queryset` model without those listed in `omit`. Will be sorted alphabetical. @@ -168,6 +161,8 @@ class GetRelatedModelsMixin: related objects in this list (e.g. to find sites of a region including child regions). omit: Remove relationships to these models from the result. Needs to be passed, if related models don't provide a `_list` view. + extra: Add extra models to the list of automatically determined related models. Can be used to add indirect + relationships. """ model = self.queryset.model related = filter( @@ -186,7 +181,7 @@ class GetRelatedModelsMixin: ) for model, field in related ] - related_models.extend(self.get_extra_related_models(request, instance)) + related_models.extend(extra) return sorted(related_models, key=lambda x: x[0].model._meta.verbose_name.lower())