Closes #13794: Dynamically populate related objects list under tenant view (#14196)

* Closes #13794: Dynamically populate related objects list under tenant view

* get_related_models() should sort models alphabetically by default

* Reference Meta.related_objects instead of calling get_fields()
This commit is contained in:
Jeremy Stretch 2023-11-16 12:02:32 -05:00 committed by GitHub
parent 840b7d804c
commit 69a4c31072
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 33 deletions

View File

@ -2,14 +2,9 @@ from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as _
from circuits.models import Circuit
from dcim.models import Cable, Device, Location, PowerFeed, Rack, RackReservation, Site, VirtualDeviceContext
from ipam.models import Aggregate, ASN, IPAddress, IPRange, L2VPN, Prefix, VLAN, VRF
from netbox.views import generic
from utilities.utils import count_related
from utilities.utils import count_related, get_related_models
from utilities.views import register_model_view, ViewTab
from virtualization.models import VirtualMachine, Cluster
from wireless.models import WirelessLAN, WirelessLink
from . import filtersets, forms, tables
from .models import *
@ -132,32 +127,8 @@ class TenantView(generic.ObjectView):
def get_extra_context(self, request, instance):
related_models = [
# DCIM
(Site.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(Rack.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(RackReservation.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(Location.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(Device.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(VirtualDeviceContext.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(Cable.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(PowerFeed.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
# IPAM
(VRF.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(Aggregate.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(Prefix.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(IPRange.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(IPAddress.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(ASN.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(VLAN.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(L2VPN.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
# Circuits
(Circuit.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
# Virtualization
(VirtualMachine.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(Cluster.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
# Wireless
(WirelessLAN.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(WirelessLink.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
(model.objects.restrict(request.user, 'view').filter(tenant=instance), f'{field}_id')
for model, field in get_related_models(Tenant)
]
return {

View File

@ -8,7 +8,7 @@ from itertools import count, groupby
import bleach
from django.contrib.contenttypes.models import ContentType
from django.core import serializers
from django.db.models import Count, OuterRef, Subquery
from django.db.models import Count, ManyToOneRel, OuterRef, Subquery
from django.db.models.functions import Coalesce
from django.http import QueryDict
from django.utils import timezone
@ -567,3 +567,20 @@ def local_now():
Return the current date & time in the system timezone.
"""
return localtime(timezone.now())
def get_related_models(model, ordered=True):
"""
Return a list of all models which have a ForeignKey to the given model and the name of the field. For example,
`get_related_models(Tenant)` will return all models which have a ForeignKey relationship to Tenant.
"""
related_models = [
(field.related_model, field.remote_field.name)
for field in model._meta.related_objects
if type(field) is ManyToOneRel
]
if ordered:
return sorted(related_models, key=lambda x: x[0]._meta.verbose_name)
return related_models