diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py index 67869f007..8e58cfffa 100644 --- a/netbox/circuits/views.py +++ b/netbox/circuits/views.py @@ -26,11 +26,9 @@ class ProviderListView(generic.ObjectListView): class ProviderView(generic.ObjectView): queryset = Provider.objects.all() - def get(self, request, slug): - - provider = get_object_or_404(self.queryset, slug=slug) + def get_extra_context(self, request, instance): circuits = Circuit.objects.restrict(request.user, 'view').filter( - provider=provider + provider=instance ).prefetch_related( 'type', 'tenant', 'terminations__site' ).annotate_sites() @@ -44,10 +42,9 @@ class ProviderView(generic.ObjectView): } RequestConfig(request, paginate).configure(circuits_table) - return render(request, 'circuits/provider.html', { - 'object': provider, + return { 'circuits_table': circuits_table, - }) + } class ProviderEditView(generic.ObjectEditView): @@ -124,30 +121,30 @@ class CircuitListView(generic.ObjectListView): class CircuitView(generic.ObjectView): queryset = Circuit.objects.all() - def get(self, request, pk): - circuit = get_object_or_404(self.queryset, pk=pk) + def get_extra_context(self, request, instance): + # A-side termination termination_a = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related( 'site__region' ).filter( - circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_A + circuit=instance, term_side=CircuitTerminationSideChoices.SIDE_A ).first() if termination_a and termination_a.connected_endpoint: termination_a.ip_addresses = termination_a.connected_endpoint.ip_addresses.restrict(request.user, 'view') + # Z-side termination termination_z = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related( 'site__region' ).filter( - circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_Z + circuit=instance, term_side=CircuitTerminationSideChoices.SIDE_Z ).first() if termination_z and termination_z.connected_endpoint: termination_z.ip_addresses = termination_z.connected_endpoint.ip_addresses.restrict(request.user, 'view') - return render(request, 'circuits/circuit.html', { - 'object': circuit, + return { 'termination_a': termination_a, 'termination_z': termination_z, - }) + } class CircuitEditView(generic.ObjectEditView): diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 879f1a7cf..77002a978 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -152,16 +152,14 @@ class SiteListView(generic.ObjectListView): class SiteView(generic.ObjectView): queryset = Site.objects.prefetch_related('region', 'tenant__group') - def get(self, request, slug): - - site = get_object_or_404(self.queryset, slug=slug) + def get_extra_context(self, request, instance): stats = { - 'rack_count': Rack.objects.restrict(request.user, 'view').filter(site=site).count(), - 'device_count': Device.objects.restrict(request.user, 'view').filter(site=site).count(), - 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(site=site).count(), - 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=site).count(), - 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=site).count(), - 'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=site).count(), + 'rack_count': Rack.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'device_count': Device.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).count(), + 'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance).count(), } rack_groups = RackGroup.objects.add_related_count( RackGroup.objects.all(), @@ -169,13 +167,12 @@ class SiteView(generic.ObjectView): 'group', 'rack_count', cumulative=True - ).restrict(request.user, 'view').filter(site=site) + ).restrict(request.user, 'view').filter(site=instance) - return render(request, 'dcim/site.html', { - 'object': site, + return { 'stats': stats, 'rack_groups': rack_groups, - }) + } class SiteEditView(generic.ObjectEditView): @@ -338,36 +335,37 @@ class RackElevationListView(generic.ObjectListView): class RackView(generic.ObjectView): queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'group', 'role') - def get(self, request, pk): - rack = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Get 0U and child devices located within the rack nonracked_devices = Device.objects.filter( - rack=rack, + rack=instance, position__isnull=True ).prefetch_related('device_type__manufacturer') - peer_racks = Rack.objects.restrict(request.user, 'view').filter(site=rack.site) + peer_racks = Rack.objects.restrict(request.user, 'view').filter(site=instance.site) - if rack.group: - peer_racks = peer_racks.filter(group=rack.group) + if instance.group: + peer_racks = peer_racks.filter(group=instance.group) else: peer_racks = peer_racks.filter(group__isnull=True) - next_rack = peer_racks.filter(name__gt=rack.name).order_by('name').first() - prev_rack = peer_racks.filter(name__lt=rack.name).order_by('-name').first() + next_rack = peer_racks.filter(name__gt=instance.name).order_by('name').first() + prev_rack = peer_racks.filter(name__lt=instance.name).order_by('-name').first() - reservations = RackReservation.objects.restrict(request.user, 'view').filter(rack=rack) - power_feeds = PowerFeed.objects.restrict(request.user, 'view').filter(rack=rack).prefetch_related('power_panel') + reservations = RackReservation.objects.restrict(request.user, 'view').filter(rack=instance) + power_feeds = PowerFeed.objects.restrict(request.user, 'view').filter(rack=instance).prefetch_related( + 'power_panel' + ) - return render(request, 'dcim/rack.html', { - 'object': rack, - 'device_count': Device.objects.restrict(request.user, 'view').filter(rack=rack).count(), + device_count = Device.objects.restrict(request.user, 'view').filter(rack=instance).count() + + return { + 'device_count': device_count, 'reservations': reservations, 'power_feeds': power_feeds, 'nonracked_devices': nonracked_devices, 'next_rack': next_rack, 'prev_rack': prev_rack, - }) + } class RackEditView(generic.ObjectEditView): @@ -511,42 +509,40 @@ class DeviceTypeListView(generic.ObjectListView): class DeviceTypeView(generic.ObjectView): queryset = DeviceType.objects.prefetch_related('manufacturer') - def get(self, request, pk): - - devicetype = get_object_or_404(self.queryset, pk=pk) - instance_count = Device.objects.restrict(request.user).filter(device_type=devicetype).count() + def get_extra_context(self, request, instance): + instance_count = Device.objects.restrict(request.user).filter(device_type=instance).count() # Component tables consoleport_table = tables.ConsolePortTemplateTable( - ConsolePortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + ConsolePortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) consoleserverport_table = tables.ConsoleServerPortTemplateTable( - ConsoleServerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + ConsoleServerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) powerport_table = tables.PowerPortTemplateTable( - PowerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + PowerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) poweroutlet_table = tables.PowerOutletTemplateTable( - PowerOutletTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + PowerOutletTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) interface_table = tables.InterfaceTemplateTable( - list(InterfaceTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype)), + list(InterfaceTemplate.objects.restrict(request.user, 'view').filter(device_type=instance)), orderable=False ) front_port_table = tables.FrontPortTemplateTable( - FrontPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + FrontPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) rear_port_table = tables.RearPortTemplateTable( - RearPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + RearPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) devicebay_table = tables.DeviceBayTemplateTable( - DeviceBayTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + DeviceBayTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) if request.user.has_perm('dcim.change_devicetype'): @@ -559,8 +555,7 @@ class DeviceTypeView(generic.ObjectView): rear_port_table.columns.show('pk') devicebay_table.columns.show('pk') - return render(request, 'dcim/devicetype.html', { - 'object': devicetype, + return { 'instance_count': instance_count, 'consoleport_table': consoleport_table, 'consoleserverport_table': consoleserverport_table, @@ -570,7 +565,7 @@ class DeviceTypeView(generic.ObjectView): 'front_port_table': front_port_table, 'rear_port_table': rear_port_table, 'devicebay_table': devicebay_table, - }) + } class DeviceTypeEditView(generic.ObjectEditView): @@ -986,51 +981,47 @@ class DeviceView(generic.ObjectView): queryset = Device.objects.prefetch_related( 'site__region', 'rack__group', 'tenant__group', 'device_role', 'platform', 'primary_ip4', 'primary_ip6' ) + template_name = 'dcim/device/device.html' - def get(self, request, pk): - - device = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # VirtualChassis members - if device.virtual_chassis is not None: + if instance.virtual_chassis is not None: vc_members = Device.objects.restrict(request.user, 'view').filter( - virtual_chassis=device.virtual_chassis + virtual_chassis=instance.virtual_chassis ).order_by('vc_position') else: vc_members = [] # Services - services = Service.objects.restrict(request.user, 'view').filter(device=device) + services = Service.objects.restrict(request.user, 'view').filter(device=instance) # Secrets - secrets = Secret.objects.restrict(request.user, 'view').filter(device=device) + secrets = Secret.objects.restrict(request.user, 'view').filter(device=instance) # Find up to ten devices in the same site with the same functional role for quick reference. related_devices = Device.objects.restrict(request.user, 'view').filter( - site=device.site, device_role=device.device_role + site=instance.site, device_role=instance.device_role ).exclude( - pk=device.pk + pk=instance.pk ).prefetch_related( 'rack', 'device_type__manufacturer' )[:10] - return render(request, 'dcim/device/device.html', { - 'object': device, + return { 'services': services, 'secrets': secrets, 'vc_members': vc_members, 'related_devices': related_devices, 'active_tab': 'device', - }) + } class DeviceConsolePortsView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/consoleports.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - - consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + def get_extra_context(self, request, instance): + consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( 'cable', '_path__destination', ) consoleport_table = tables.DeviceConsolePortTable( @@ -1041,21 +1032,19 @@ class DeviceConsolePortsView(generic.ObjectView): if request.user.has_perm('dcim.change_consoleport') or request.user.has_perm('dcim.delete_consoleport'): consoleport_table.columns.show('pk') - return render(request, 'dcim/device/consoleports.html', { - 'object': device, + return { 'consoleport_table': consoleport_table, 'active_tab': 'console-ports', - }) + } class DeviceConsoleServerPortsView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/consoleserverports.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter( - device=device + device=instance ).prefetch_related( 'cable', '_path__destination', ) @@ -1068,20 +1057,18 @@ class DeviceConsoleServerPortsView(generic.ObjectView): request.user.has_perm('dcim.delete_consoleserverport'): consoleserverport_table.columns.show('pk') - return render(request, 'dcim/device/consoleserverports.html', { - 'object': device, + return { 'consoleserverport_table': consoleserverport_table, 'active_tab': 'console-server-ports', - }) + } class DevicePowerPortsView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/powerports.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - - powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + def get_extra_context(self, request, instance): + powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( 'cable', '_path__destination', ) powerport_table = tables.DevicePowerPortTable( @@ -1092,20 +1079,18 @@ class DevicePowerPortsView(generic.ObjectView): if request.user.has_perm('dcim.change_powerport') or request.user.has_perm('dcim.delete_powerport'): powerport_table.columns.show('pk') - return render(request, 'dcim/device/powerports.html', { - 'object': device, + return { 'powerport_table': powerport_table, 'active_tab': 'power-ports', - }) + } class DevicePowerOutletsView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/poweroutlets.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - - poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + def get_extra_context(self, request, instance): + poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( 'cable', 'power_port', '_path__destination', ) poweroutlet_table = tables.DevicePowerOutletTable( @@ -1116,20 +1101,18 @@ class DevicePowerOutletsView(generic.ObjectView): if request.user.has_perm('dcim.change_poweroutlet') or request.user.has_perm('dcim.delete_poweroutlet'): poweroutlet_table.columns.show('pk') - return render(request, 'dcim/device/poweroutlets.html', { - 'object': device, + return { 'poweroutlet_table': poweroutlet_table, 'active_tab': 'power-outlets', - }) + } class DeviceInterfacesView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/interfaces.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - - interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related( + def get_extra_context(self, request, instance): + interfaces = instance.vc_interfaces.restrict(request.user, 'view').prefetch_related( Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)), Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), 'lag', 'cable', '_path__destination', 'tags', @@ -1142,20 +1125,18 @@ class DeviceInterfacesView(generic.ObjectView): if request.user.has_perm('dcim.change_interface') or request.user.has_perm('dcim.delete_interface'): interface_table.columns.show('pk') - return render(request, 'dcim/device/interfaces.html', { - 'object': device, + return { 'interface_table': interface_table, 'active_tab': 'interfaces', - }) + } class DeviceFrontPortsView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/frontports.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - - frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + def get_extra_context(self, request, instance): + frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( 'rear_port', 'cable', ) frontport_table = tables.DeviceFrontPortTable( @@ -1166,20 +1147,18 @@ class DeviceFrontPortsView(generic.ObjectView): if request.user.has_perm('dcim.change_frontport') or request.user.has_perm('dcim.delete_frontport'): frontport_table.columns.show('pk') - return render(request, 'dcim/device/frontports.html', { - 'object': device, + return { 'frontport_table': frontport_table, 'active_tab': 'front-ports', - }) + } class DeviceRearPortsView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/rearports.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - - rearports = RearPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related('cable') + def get_extra_context(self, request, instance): + rearports = RearPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related('cable') rearport_table = tables.DeviceRearPortTable( data=rearports, user=request.user, @@ -1188,20 +1167,18 @@ class DeviceRearPortsView(generic.ObjectView): if request.user.has_perm('dcim.change_rearport') or request.user.has_perm('dcim.delete_rearport'): rearport_table.columns.show('pk') - return render(request, 'dcim/device/rearports.html', { - 'object': device, + return { 'rearport_table': rearport_table, 'active_tab': 'rear-ports', - }) + } class DeviceDeviceBaysView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/devicebays.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - - devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + def get_extra_context(self, request, instance): + devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( 'installed_device__device_type__manufacturer', ) devicebay_table = tables.DeviceDeviceBayTable( @@ -1212,21 +1189,19 @@ class DeviceDeviceBaysView(generic.ObjectView): if request.user.has_perm('dcim.change_devicebay') or request.user.has_perm('dcim.delete_devicebay'): devicebay_table.columns.show('pk') - return render(request, 'dcim/device/devicebays.html', { - 'object': device, + return { 'devicebay_table': devicebay_table, 'active_tab': 'device-bays', - }) + } class DeviceInventoryView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/inventory.html' - def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): inventoryitems = InventoryItem.objects.restrict(request.user, 'view').filter( - device=device + device=instance ).prefetch_related('manufacturer') inventoryitem_table = tables.DeviceInventoryItemTable( data=inventoryitems, @@ -1236,11 +1211,10 @@ class DeviceInventoryView(generic.ObjectView): if request.user.has_perm('dcim.change_inventoryitem') or request.user.has_perm('dcim.delete_inventoryitem'): inventoryitem_table.columns.show('pk') - return render(request, 'dcim/device/inventory.html', { - 'object': device, + return { 'inventoryitem_table': inventoryitem_table, 'active_tab': 'inventory', - }) + } class DeviceStatusView(generic.ObjectView): @@ -1248,7 +1222,7 @@ class DeviceStatusView(generic.ObjectView): queryset = Device.objects.all() template_name = 'dcim/device/status.html' - def get_extra_context(self): + def get_extra_context(self, request, instance): return { 'active_tab': 'status', } @@ -1257,19 +1231,19 @@ class DeviceStatusView(generic.ObjectView): class DeviceLLDPNeighborsView(generic.ObjectView): additional_permissions = ['dcim.napalm_read_device'] queryset = Device.objects.all() + template_name = 'dcim/device/lldp_neighbors.html' - def get(self, request, pk): - - device = get_object_or_404(self.queryset, pk=pk) - interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related('_path__destination').exclude( + def get_extra_context(self, request, instance): + interfaces = instance.vc_interfaces.restrict(request.user, 'view').prefetch_related( + '_path__destination' + ).exclude( type__in=NONCONNECTABLE_IFACE_TYPES ) - return render(request, 'dcim/device/lldp_neighbors.html', { - 'object': device, + return { 'interfaces': interfaces, 'active_tab': 'lldp-neighbors', - }) + } class DeviceConfigView(generic.ObjectView): @@ -1277,7 +1251,7 @@ class DeviceConfigView(generic.ObjectView): queryset = Device.objects.all() template_name = 'dcim/device/config.html' - def get_extra_context(self): + def get_extra_context(self, request, instance): return { 'active_tab': 'config', } @@ -1595,35 +1569,31 @@ class InterfaceListView(generic.ObjectListView): class InterfaceView(generic.ObjectView): queryset = Interface.objects.all() - def get(self, request, pk): - - interface = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Get assigned IP addresses ipaddress_table = InterfaceIPAddressTable( - data=interface.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'), + data=instance.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'), orderable=False ) # Get assigned VLANs and annotate whether each is tagged or untagged vlans = [] - if interface.untagged_vlan is not None: - vlans.append(interface.untagged_vlan) + if instance.untagged_vlan is not None: + vlans.append(instance.untagged_vlan) vlans[0].tagged = False - for vlan in interface.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): + for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): vlan.tagged = True vlans.append(vlan) vlan_table = InterfaceVLANTable( - interface=interface, + interface=instance, data=vlans, orderable=False ) - return render(request, 'dcim/interface.html', { - 'object': interface, + return { 'ipaddress_table': ipaddress_table, 'vlan_table': vlan_table, - }) + } class InterfaceCreateView(generic.ComponentCreateView): @@ -2090,6 +2060,7 @@ class PathTraceView(generic.ObjectView): Trace a cable path beginning from the given path endpoint (origin). """ additional_permissions = ['dcim.view_cable'] + template_name = 'dcim/cable_trace.html' def dispatch(self, request, *args, **kwargs): model = kwargs.pop('model') @@ -2097,13 +2068,12 @@ class PathTraceView(generic.ObjectView): return super().dispatch(request, *args, **kwargs) - def get(self, request, pk): - obj = get_object_or_404(self.queryset, pk=pk) + def get_extra_context(self, request, instance): related_paths = [] # If tracing a PathEndpoint, locate the CablePath (if one exists) by its origin - if isinstance(obj, PathEndpoint): - path = obj._path + if isinstance(instance, PathEndpoint): + path = instance._path # Otherwise, find all CablePaths which traverse the specified object else: @@ -2118,12 +2088,11 @@ class PathTraceView(generic.ObjectView): else: path = related_paths.first() - return render(request, 'dcim/cable_trace.html', { - 'object': obj, + return { 'path': path, 'related_paths': related_paths, 'total_length': path.get_total_length() if path else None, - }) + } class CableCreateView(generic.ObjectEditView): @@ -2330,14 +2299,12 @@ class VirtualChassisListView(generic.ObjectListView): class VirtualChassisView(generic.ObjectView): queryset = VirtualChassis.objects.all() - def get(self, request, pk): - virtualchassis = get_object_or_404(self.queryset, pk=pk) - members = Device.objects.restrict(request.user).filter(virtual_chassis=virtualchassis) + def get_extra_context(self, request, instance): + members = Device.objects.restrict(request.user).filter(virtual_chassis=instance) - return render(request, 'dcim/virtualchassis.html', { - 'object': virtualchassis, + return { 'members': members, - }) + } class VirtualChassisCreateView(generic.ObjectEditView): @@ -2560,20 +2527,17 @@ class PowerPanelListView(generic.ObjectListView): class PowerPanelView(generic.ObjectView): queryset = PowerPanel.objects.prefetch_related('site', 'rack_group') - def get(self, request, pk): - - powerpanel = get_object_or_404(self.queryset, pk=pk) - power_feeds = PowerFeed.objects.restrict(request.user).filter(power_panel=powerpanel).prefetch_related('rack') + def get_extra_context(self, request, instance): + power_feeds = PowerFeed.objects.restrict(request.user).filter(power_panel=instance).prefetch_related('rack') powerfeed_table = tables.PowerFeedTable( data=power_feeds, orderable=False ) powerfeed_table.exclude = ['power_panel'] - return render(request, 'dcim/powerpanel.html', { - 'object': powerpanel, + return { 'powerfeed_table': powerfeed_table, - }) + } class PowerPanelEditView(generic.ObjectEditView): diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 4ef98a456..8f72da59b 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -83,21 +83,7 @@ class ConfigContextListView(generic.ObjectListView): class ConfigContextView(generic.ObjectView): queryset = ConfigContext.objects.all() - def get(self, request, pk): - # Extend queryset to prefetch related objects - self.queryset = self.queryset.prefetch_related( - Prefetch('regions', queryset=Region.objects.restrict(request.user)), - Prefetch('sites', queryset=Site.objects.restrict(request.user)), - Prefetch('roles', queryset=DeviceRole.objects.restrict(request.user)), - Prefetch('platforms', queryset=Platform.objects.restrict(request.user)), - Prefetch('clusters', queryset=Cluster.objects.restrict(request.user)), - Prefetch('cluster_groups', queryset=ClusterGroup.objects.restrict(request.user)), - Prefetch('tenants', queryset=Tenant.objects.restrict(request.user)), - Prefetch('tenant_groups', queryset=TenantGroup.objects.restrict(request.user)), - ) - - configcontext = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Determine user's preferred output format if request.GET.get('format') in ['json', 'yaml']: format = request.GET.get('format') @@ -108,10 +94,9 @@ class ConfigContextView(generic.ObjectView): else: format = 'json' - return render(request, 'extras/configcontext.html', { - 'object': configcontext, + return { 'format': format, - }) + } class ConfigContextEditView(generic.ObjectEditView): @@ -138,12 +123,10 @@ class ConfigContextBulkDeleteView(generic.BulkDeleteView): class ObjectConfigContextView(generic.ObjectView): base_template = None + template_name = 'extras/object_configcontext.html' - def get(self, request, pk): - - obj = get_object_or_404(self.queryset, pk=pk) - source_contexts = ConfigContext.objects.restrict(request.user, 'view').get_for_object(obj) - model_name = self.queryset.model._meta.model_name + def get_extra_context(self, request, instance): + source_contexts = ConfigContext.objects.restrict(request.user, 'view').get_for_object(instance) # Determine user's preferred output format if request.GET.get('format') in ['json', 'yaml']: @@ -155,14 +138,13 @@ class ObjectConfigContextView(generic.ObjectView): else: format = 'json' - return render(request, 'extras/object_configcontext.html', { - 'object': obj, - 'rendered_context': obj.get_config_context(), + return { + 'rendered_context': instance.get_config_context(), 'source_contexts': source_contexts, 'format': format, 'base_template': self.base_template, 'active_tab': 'config-context', - }) + } # @@ -181,14 +163,11 @@ class ObjectChangeListView(generic.ObjectListView): class ObjectChangeView(generic.ObjectView): queryset = ObjectChange.objects.all() - def get(self, request, pk): - - objectchange = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): related_changes = ObjectChange.objects.restrict(request.user, 'view').filter( - request_id=objectchange.request_id + request_id=instance.request_id ).exclude( - pk=objectchange.pk + pk=instance.pk ) related_changes_table = tables.ObjectChangeTable( data=related_changes[:50], @@ -196,33 +175,32 @@ class ObjectChangeView(generic.ObjectView): ) objectchanges = ObjectChange.objects.restrict(request.user, 'view').filter( - changed_object_type=objectchange.changed_object_type, - changed_object_id=objectchange.changed_object_id, + changed_object_type=instance.changed_object_type, + changed_object_id=instance.changed_object_id, ) - next_change = objectchanges.filter(time__gt=objectchange.time).order_by('time').first() - prev_change = objectchanges.filter(time__lt=objectchange.time).order_by('-time').first() + next_change = objectchanges.filter(time__gt=instance.time).order_by('time').first() + prev_change = objectchanges.filter(time__lt=instance.time).order_by('-time').first() if prev_change: diff_added = shallow_compare_dict( prev_change.object_data, - objectchange.object_data, + instance.object_data, exclude=['last_updated'], ) diff_removed = {x: prev_change.object_data.get(x) for x in diff_added} else: # No previous change; this is the initial change that added the object - diff_added = diff_removed = objectchange.object_data + diff_added = diff_removed = instance.object_data - return render(request, 'extras/objectchange.html', { - 'object': objectchange, + return { 'diff_added': diff_added, 'diff_removed': diff_removed, 'next_change': next_change, 'prev_change': prev_change, 'related_changes_table': related_changes_table, 'related_changes_count': related_changes.count() - }) + } class ObjectChangeLogView(View): diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 40d8a5207..5769f0a68 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -28,26 +28,23 @@ class VRFListView(generic.ObjectListView): class VRFView(generic.ObjectView): queryset = VRF.objects.all() - def get(self, request, pk): - - vrf = get_object_or_404(self.queryset, pk=pk) - prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=vrf).count() + def get_extra_context(self, request, instance): + prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=instance).count() import_targets_table = tables.RouteTargetTable( - vrf.import_targets.prefetch_related('tenant'), + instance.import_targets.prefetch_related('tenant'), orderable=False ) export_targets_table = tables.RouteTargetTable( - vrf.export_targets.prefetch_related('tenant'), + instance.export_targets.prefetch_related('tenant'), orderable=False ) - return render(request, 'ipam/vrf.html', { - 'object': vrf, + return { 'prefix_count': prefix_count, 'import_targets_table': import_targets_table, 'export_targets_table': export_targets_table, - }) + } class VRFEditView(generic.ObjectEditView): @@ -93,23 +90,20 @@ class RouteTargetListView(generic.ObjectListView): class RouteTargetView(generic.ObjectView): queryset = RouteTarget.objects.all() - def get(self, request, pk): - routetarget = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): importing_vrfs_table = tables.VRFTable( - routetarget.importing_vrfs.prefetch_related('tenant'), + instance.importing_vrfs.prefetch_related('tenant'), orderable=False ) exporting_vrfs_table = tables.VRFTable( - routetarget.exporting_vrfs.prefetch_related('tenant'), + instance.exporting_vrfs.prefetch_related('tenant'), orderable=False ) - return render(request, 'ipam/routetarget.html', { - 'object': routetarget, + return { 'importing_vrfs_table': importing_vrfs_table, 'exporting_vrfs_table': exporting_vrfs_table, - }) + } class RouteTargetEditView(generic.ObjectEditView): @@ -206,13 +200,10 @@ class AggregateListView(generic.ObjectListView): class AggregateView(generic.ObjectView): queryset = Aggregate.objects.all() - def get(self, request, pk): - - aggregate = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Find all child prefixes contained by this aggregate child_prefixes = Prefix.objects.restrict(request.user, 'view').filter( - prefix__net_contained_or_equal=str(aggregate.prefix) + prefix__net_contained_or_equal=str(instance.prefix) ).prefetch_related( 'site', 'role' ).order_by( @@ -221,7 +212,7 @@ class AggregateView(generic.ObjectView): # Add available prefixes to the table if requested if request.GET.get('show_available', 'true') == 'true': - child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes) + child_prefixes = add_available_prefixes(instance.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): @@ -240,12 +231,11 @@ class AggregateView(generic.ObjectView): 'delete': request.user.has_perm('ipam.delete_prefix'), } - return render(request, 'ipam/aggregate.html', { - 'object': aggregate, + return { 'prefix_table': prefix_table, 'permissions': permissions, 'show_available': request.GET.get('show_available', 'true') == 'true', - }) + } class AggregateEditView(generic.ObjectEditView): @@ -324,22 +314,19 @@ class PrefixListView(generic.ObjectListView): class PrefixView(generic.ObjectView): queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role') - def get(self, request, pk): - - prefix = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): try: aggregate = Aggregate.objects.restrict(request.user, 'view').get( - prefix__net_contains_or_equals=str(prefix.prefix) + prefix__net_contains_or_equals=str(instance.prefix) ) except Aggregate.DoesNotExist: aggregate = None # Parent prefixes table parent_prefixes = Prefix.objects.restrict(request.user, 'view').filter( - Q(vrf=prefix.vrf) | Q(vrf__isnull=True) + Q(vrf=instance.vrf) | Q(vrf__isnull=True) ).filter( - prefix__net_contains=str(prefix.prefix) + prefix__net_contains=str(instance.prefix) ).prefetch_related( 'site', 'role' ).annotate_tree() @@ -348,38 +335,35 @@ class PrefixView(generic.ObjectView): # Duplicate prefixes table duplicate_prefixes = Prefix.objects.restrict(request.user, 'view').filter( - vrf=prefix.vrf, prefix=str(prefix.prefix) + vrf=instance.vrf, prefix=str(instance.prefix) ).exclude( - pk=prefix.pk + pk=instance.pk ).prefetch_related( 'site', 'role' ) duplicate_prefix_table = tables.PrefixTable(list(duplicate_prefixes), orderable=False) duplicate_prefix_table.exclude = ('vrf',) - return render(request, 'ipam/prefix.html', { - 'object': prefix, + return { 'aggregate': aggregate, 'parent_prefix_table': parent_prefix_table, 'duplicate_prefix_table': duplicate_prefix_table, - }) + } class PrefixPrefixesView(generic.ObjectView): queryset = Prefix.objects.all() + template_name = 'ipam/prefix_prefixes.html' - def get(self, request, pk): - - prefix = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Child prefixes table - child_prefixes = prefix.get_child_prefixes().restrict(request.user, 'view').prefetch_related( + child_prefixes = instance.get_child_prefixes().restrict(request.user, 'view').prefetch_related( 'site', 'vlan', 'role', ).annotate_tree() # Add available prefixes to the table if requested if child_prefixes and request.GET.get('show_available', 'true') == 'true': - child_prefixes = add_available_prefixes(prefix.prefix, child_prefixes) + child_prefixes = add_available_prefixes(instance.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): @@ -398,32 +382,31 @@ class PrefixPrefixesView(generic.ObjectView): 'delete': request.user.has_perm('ipam.delete_prefix'), } - return render(request, 'ipam/prefix_prefixes.html', { - 'object': prefix, - 'first_available_prefix': prefix.get_first_available_prefix(), + bulk_querystring = 'vrf_id={}&within={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix) + + return { + 'first_available_prefix': instance.get_first_available_prefix(), 'prefix_table': prefix_table, 'permissions': permissions, - 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), + 'bulk_querystring': bulk_querystring, 'active_tab': 'prefixes', 'show_available': request.GET.get('show_available', 'true') == 'true', - }) + } class PrefixIPAddressesView(generic.ObjectView): queryset = Prefix.objects.all() + template_name = 'ipam/prefix_ipaddresses.html' - def get(self, request, pk): - - prefix = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Find all IPAddresses belonging to this Prefix - ipaddresses = prefix.get_child_ips().restrict(request.user, 'view').prefetch_related( + ipaddresses = instance.get_child_ips().restrict(request.user, 'view').prefetch_related( 'vrf', 'primary_ip4_for', 'primary_ip6_for' ) # Add available IP addresses to the table if requested if request.GET.get('show_available', 'true') == 'true': - ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool) + ipaddresses = add_available_ipaddresses(instance.prefix, ipaddresses, instance.is_pool) ip_table = tables.IPAddressTable(ipaddresses) if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'): @@ -442,15 +425,16 @@ class PrefixIPAddressesView(generic.ObjectView): 'delete': request.user.has_perm('ipam.delete_ipaddress'), } - return render(request, 'ipam/prefix_ipaddresses.html', { - 'object': prefix, - 'first_available_ip': prefix.get_first_available_ip(), + bulk_querystring = 'vrf_id={}&parent={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix) + + return { + 'first_available_ip': instance.get_first_available_ip(), 'ip_table': ip_table, 'permissions': permissions, - 'bulk_querystring': 'vrf_id={}&parent={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), + 'bulk_querystring': bulk_querystring, 'active_tab': 'ip-addresses', 'show_available': request.GET.get('show_available', 'true') == 'true', - }) + } class PrefixEditView(generic.ObjectEditView): @@ -497,13 +481,11 @@ class IPAddressListView(generic.ObjectListView): class IPAddressView(generic.ObjectView): queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant') - def get(self, request, pk): - - ipaddress = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Parent prefixes table parent_prefixes = Prefix.objects.restrict(request.user, 'view').filter( - vrf=ipaddress.vrf, prefix__net_contains=str(ipaddress.address.ip) + vrf=instance.vrf, + prefix__net_contains=str(instance.address.ip) ).prefetch_related( 'site', 'role' ) @@ -512,23 +494,24 @@ class IPAddressView(generic.ObjectView): # Duplicate IPs table duplicate_ips = IPAddress.objects.restrict(request.user, 'view').filter( - vrf=ipaddress.vrf, address=str(ipaddress.address) + vrf=instance.vrf, + address=str(instance.address) ).exclude( - pk=ipaddress.pk + pk=instance.pk ).prefetch_related( 'nat_inside' ) # Exclude anycast IPs if this IP is anycast - if ipaddress.role == IPAddressRoleChoices.ROLE_ANYCAST: + if instance.role == IPAddressRoleChoices.ROLE_ANYCAST: duplicate_ips = duplicate_ips.exclude(role=IPAddressRoleChoices.ROLE_ANYCAST) # Limit to a maximum of 10 duplicates displayed here duplicate_ips_table = tables.IPAddressTable(duplicate_ips[:10], orderable=False) # Related IP table related_ips = IPAddress.objects.restrict(request.user, 'view').exclude( - address=str(ipaddress.address) + address=str(instance.address) ).filter( - vrf=ipaddress.vrf, address__net_contained_or_equal=str(ipaddress.address) + vrf=instance.vrf, address__net_contained_or_equal=str(instance.address) ) related_ips_table = tables.IPAddressTable(related_ips, orderable=False) @@ -538,13 +521,12 @@ class IPAddressView(generic.ObjectView): } RequestConfig(request, paginate).configure(related_ips_table) - return render(request, 'ipam/ipaddress.html', { - 'object': ipaddress, + return { 'parent_prefixes_table': parent_prefixes_table, 'duplicate_ips_table': duplicate_ips_table, 'more_duplicate_ips': duplicate_ips.count() > 10, 'related_ips_table': related_ips_table, - }) + } class IPAddressEditView(generic.ObjectEditView): @@ -569,6 +551,7 @@ class IPAddressEditView(generic.ObjectEditView): return obj +# TODO: Standardize or remove this view class IPAddressAssignView(generic.ObjectView): """ Search for IPAddresses to be assigned to an Interface. @@ -678,14 +661,13 @@ class VLANGroupBulkDeleteView(generic.BulkDeleteView): class VLANGroupVLANsView(generic.ObjectView): queryset = VLANGroup.objects.all() + template_name = 'ipam/vlangroup_vlans.html' - def get(self, request, pk): - vlan_group = get_object_or_404(self.queryset, pk=pk) - - vlans = VLAN.objects.restrict(request.user, 'view').filter(group_id=pk).prefetch_related( + def get_extra_context(self, request, instance): + vlans = VLAN.objects.restrict(request.user, 'view').filter(group=instance).prefetch_related( Prefetch('prefixes', queryset=Prefix.objects.restrict(request.user)) ) - vlans = add_available_vlans(vlan_group, vlans) + vlans = add_available_vlans(instance, vlans) vlan_table = tables.VLANDetailTable(vlans) if request.user.has_perm('ipam.change_vlan') or request.user.has_perm('ipam.delete_vlan'): @@ -706,13 +688,12 @@ class VLANGroupVLANsView(generic.ObjectView): 'delete': request.user.has_perm('ipam.delete_vlan'), } - return render(request, 'ipam/vlangroup_vlans.html', { - 'vlan_group': vlan_group, - 'first_available_vlan': vlan_group.get_next_available_vid(), - 'bulk_querystring': 'group_id={}'.format(vlan_group.pk), + return { + 'first_available_vlan': instance.get_next_available_vid(), + 'bulk_querystring': f'group_id={instance.pk}', 'vlan_table': vlan_table, 'permissions': permissions, - }) + } # @@ -729,27 +710,24 @@ class VLANListView(generic.ObjectListView): class VLANView(generic.ObjectView): queryset = VLAN.objects.prefetch_related('site__region', 'tenant__group', 'role') - def get(self, request, pk): - - vlan = get_object_or_404(self.queryset, pk=pk) - prefixes = Prefix.objects.restrict(request.user, 'view').filter(vlan=vlan).prefetch_related( + def get_extra_context(self, request, instance): + prefixes = Prefix.objects.restrict(request.user, 'view').filter(vlan=instance).prefetch_related( 'vrf', 'site', 'role' ) prefix_table = tables.PrefixTable(list(prefixes), orderable=False) prefix_table.exclude = ('vlan',) - return render(request, 'ipam/vlan.html', { - 'object': vlan, + return { 'prefix_table': prefix_table, - }) + } class VLANInterfacesView(generic.ObjectView): queryset = VLAN.objects.all() + template_name = 'ipam/vlan_interfaces.html' - def get(self, request, pk): - vlan = get_object_or_404(self.queryset, pk=pk) - interfaces = vlan.get_interfaces().prefetch_related('device') + def get_extra_context(self, request, instance): + interfaces = instance.get_interfaces().prefetch_related('device') members_table = tables.VLANDevicesTable(interfaces) paginate = { @@ -758,19 +736,18 @@ class VLANInterfacesView(generic.ObjectView): } RequestConfig(request, paginate).configure(members_table) - return render(request, 'ipam/vlan_interfaces.html', { - 'object': vlan, + return { 'members_table': members_table, 'active_tab': 'interfaces', - }) + } class VLANVMInterfacesView(generic.ObjectView): queryset = VLAN.objects.all() + template_name = 'ipam/vlan_vminterfaces.html' - def get(self, request, pk): - vlan = get_object_or_404(self.queryset, pk=pk) - interfaces = vlan.get_vminterfaces().prefetch_related('virtual_machine') + def get_extra_context(self, request, instance): + interfaces = instance.get_vminterfaces().prefetch_related('virtual_machine') members_table = tables.VLANVirtualMachinesTable(interfaces) paginate = { @@ -779,11 +756,10 @@ class VLANVMInterfacesView(generic.ObjectView): } RequestConfig(request, paginate).configure(members_table) - return render(request, 'ipam/vlan_vminterfaces.html', { - 'object': vlan, + return { 'members_table': members_table, 'active_tab': 'vminterfaces', - }) + } class VLANEditView(generic.ObjectEditView): diff --git a/netbox/netbox/views/generic.py b/netbox/netbox/views/generic.py index f8d2e028b..eb7b2542f 100644 --- a/netbox/netbox/views/generic.py +++ b/netbox/netbox/views/generic.py @@ -32,9 +32,11 @@ class ObjectView(ObjectPermissionRequiredMixin, View): """ Retrieve a single object for display. - queryset: The base queryset for retrieving the object. + queryset: The base queryset for retrieving the object + template_name: Name of the template to use """ queryset = None + template_name = None def get_required_permission(self): return get_permission_for_model(self.queryset.model, 'view') @@ -43,14 +45,17 @@ class ObjectView(ObjectPermissionRequiredMixin, View): """ Return self.template_name if set. Otherwise, resolve the template path by model app_label and name. """ - if hasattr(self, 'template_name'): + if self.template_name is not None: return self.template_name model_opts = self.queryset.model._meta return f'{model_opts.app_label}/{model_opts.model_name}.html' - def get_extra_context(self): + def get_extra_context(self, request, instance): """ Return any additional context data for the template. + + request: The current request + instance: The object being viewed """ return {} @@ -58,11 +63,11 @@ class ObjectView(ObjectPermissionRequiredMixin, View): """ Generic GET handler for accessing an object by PK or slug """ - obj = get_object_or_404(self.queryset, **kwargs) + instance = get_object_or_404(self.queryset, **kwargs) return render(request, self.get_template_name(), { - 'object': obj, - **self.get_extra_context(), + 'object': instance, + **self.get_extra_context(request, instance), }) diff --git a/netbox/templates/ipam/inc/vlangroup_header.html b/netbox/templates/ipam/inc/vlangroup_header.html index 55d82c39f..2507a749f 100644 --- a/netbox/templates/ipam/inc/vlangroup_header.html +++ b/netbox/templates/ipam/inc/vlangroup_header.html @@ -1,14 +1,14 @@
{% if perms.ipam.add_vlan and first_available_vlan %} - + Add a VLAN {% endif %} {% if perms.ipam.change_vlangroup %} - + Edit this VLAN Group {% endif %}
-

{{ vlan_group }}

+

{{ object }}

diff --git a/netbox/templates/ipam/vlangroup_vlans.html b/netbox/templates/ipam/vlangroup_vlans.html index 7f8ac2044..490b7ab2c 100644 --- a/netbox/templates/ipam/vlangroup_vlans.html +++ b/netbox/templates/ipam/vlangroup_vlans.html @@ -1,16 +1,16 @@ {% extends 'base.html' %} -{% block title %}{{ vlan_group }} - VLANs{% endblock %} +{% block title %}{{ object }} - VLANs{% endblock %} {% block content %}
diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 24a256691..0f4a0416d 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -250,7 +250,7 @@ {% endif %} {% if perms.ipam.add_service %} diff --git a/netbox/tenancy/views.py b/netbox/tenancy/views.py index 015228d42..9fd77d88e 100644 --- a/netbox/tenancy/views.py +++ b/netbox/tenancy/views.py @@ -64,27 +64,24 @@ class TenantListView(generic.ObjectListView): class TenantView(generic.ObjectView): queryset = Tenant.objects.prefetch_related('group') - def get(self, request, slug): - - tenant = get_object_or_404(self.queryset, slug=slug) + def get_extra_context(self, request, instance): stats = { - 'site_count': Site.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'rack_count': Rack.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'rackreservation_count': RackReservation.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'device_count': Device.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'vrf_count': VRF.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'cluster_count': Cluster.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), + 'site_count': Site.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'rack_count': Rack.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'rackreservation_count': RackReservation.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'device_count': Device.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'vrf_count': VRF.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'cluster_count': Cluster.objects.restrict(request.user, 'view').filter(tenant=instance).count(), } - return render(request, 'tenancy/tenant.html', { - 'object': tenant, + return { 'stats': stats, - }) + } class TenantEditView(generic.ObjectEditView): diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index a42888a3c..3c3b0b478 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -92,23 +92,17 @@ class ClusterListView(generic.ObjectListView): class ClusterView(generic.ObjectView): queryset = Cluster.objects.all() - def get(self, request, pk): - self.queryset = self.queryset.prefetch_related( - Prefetch('virtual_machines', queryset=VirtualMachine.objects.restrict(request.user)) - ) - - cluster = get_object_or_404(self.queryset, pk=pk) - devices = Device.objects.restrict(request.user, 'view').filter(cluster=cluster).prefetch_related( + def get_extra_context(self, request, instance): + devices = Device.objects.restrict(request.user, 'view').filter(cluster=instance).prefetch_related( 'site', 'rack', 'tenant', 'device_type__manufacturer' ) device_table = DeviceTable(list(devices), orderable=False) if request.user.has_perm('virtualization.change_cluster'): device_table.columns.show('pk') - return render(request, 'virtualization/cluster.html', { - 'object': cluster, + return { 'device_table': device_table, - }) + } class ClusterEditView(generic.ObjectEditView): @@ -237,12 +231,10 @@ class VirtualMachineListView(generic.ObjectListView): class VirtualMachineView(generic.ObjectView): queryset = VirtualMachine.objects.prefetch_related('tenant__group') - def get(self, request, pk): - virtualmachine = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Interfaces vminterfaces = VMInterface.objects.restrict(request.user, 'view').filter( - virtual_machine=virtualmachine + virtual_machine=instance ).prefetch_related( Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)) ) @@ -253,20 +245,19 @@ class VirtualMachineView(generic.ObjectView): # Services services = Service.objects.restrict(request.user, 'view').filter( - virtual_machine=virtualmachine + virtual_machine=instance ).prefetch_related( Prefetch('ipaddresses', queryset=IPAddress.objects.restrict(request.user)) ) # Secrets - secrets = Secret.objects.restrict(request.user, 'view').filter(virtual_machine=virtualmachine) + secrets = Secret.objects.restrict(request.user, 'view').filter(virtual_machine=instance) - return render(request, 'virtualization/virtualmachine.html', { - 'object': virtualmachine, + return { 'vminterface_table': vminterface_table, 'services': services, 'secrets': secrets, - }) + } class VirtualMachineConfigContextView(ObjectConfigContextView): @@ -318,35 +309,31 @@ class VMInterfaceListView(generic.ObjectListView): class VMInterfaceView(generic.ObjectView): queryset = VMInterface.objects.all() - def get(self, request, pk): - - vminterface = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Get assigned IP addresses ipaddress_table = InterfaceIPAddressTable( - data=vminterface.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'), + data=instance.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'), orderable=False ) # Get assigned VLANs and annotate whether each is tagged or untagged vlans = [] - if vminterface.untagged_vlan is not None: - vlans.append(vminterface.untagged_vlan) + if instance.untagged_vlan is not None: + vlans.append(instance.untagged_vlan) vlans[0].tagged = False - for vlan in vminterface.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): + for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): vlan.tagged = True vlans.append(vlan) vlan_table = InterfaceVLANTable( - interface=vminterface, + interface=instance, data=vlans, orderable=False ) - return render(request, 'virtualization/vminterface.html', { - 'object': vminterface, + return { 'ipaddress_table': ipaddress_table, 'vlan_table': vlan_table, - }) + } # TODO: This should not use ComponentCreateView