Migrate all ObjectView subclasses to use get_extra_context()

This commit is contained in:
Jeremy Stretch 2020-11-19 15:59:11 -05:00
parent d237b97776
commit 1d922ee813
10 changed files with 284 additions and 380 deletions

View File

@ -26,11 +26,9 @@ class ProviderListView(generic.ObjectListView):
class ProviderView(generic.ObjectView): class ProviderView(generic.ObjectView):
queryset = Provider.objects.all() queryset = Provider.objects.all()
def get(self, request, slug): def get_extra_context(self, request, instance):
provider = get_object_or_404(self.queryset, slug=slug)
circuits = Circuit.objects.restrict(request.user, 'view').filter( circuits = Circuit.objects.restrict(request.user, 'view').filter(
provider=provider provider=instance
).prefetch_related( ).prefetch_related(
'type', 'tenant', 'terminations__site' 'type', 'tenant', 'terminations__site'
).annotate_sites() ).annotate_sites()
@ -44,10 +42,9 @@ class ProviderView(generic.ObjectView):
} }
RequestConfig(request, paginate).configure(circuits_table) RequestConfig(request, paginate).configure(circuits_table)
return render(request, 'circuits/provider.html', { return {
'object': provider,
'circuits_table': circuits_table, 'circuits_table': circuits_table,
}) }
class ProviderEditView(generic.ObjectEditView): class ProviderEditView(generic.ObjectEditView):
@ -124,30 +121,30 @@ class CircuitListView(generic.ObjectListView):
class CircuitView(generic.ObjectView): class CircuitView(generic.ObjectView):
queryset = Circuit.objects.all() queryset = Circuit.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
circuit = get_object_or_404(self.queryset, pk=pk)
# A-side termination
termination_a = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related( termination_a = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related(
'site__region' 'site__region'
).filter( ).filter(
circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_A circuit=instance, term_side=CircuitTerminationSideChoices.SIDE_A
).first() ).first()
if termination_a and termination_a.connected_endpoint: if termination_a and termination_a.connected_endpoint:
termination_a.ip_addresses = termination_a.connected_endpoint.ip_addresses.restrict(request.user, 'view') 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( termination_z = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related(
'site__region' 'site__region'
).filter( ).filter(
circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_Z circuit=instance, term_side=CircuitTerminationSideChoices.SIDE_Z
).first() ).first()
if termination_z and termination_z.connected_endpoint: if termination_z and termination_z.connected_endpoint:
termination_z.ip_addresses = termination_z.connected_endpoint.ip_addresses.restrict(request.user, 'view') termination_z.ip_addresses = termination_z.connected_endpoint.ip_addresses.restrict(request.user, 'view')
return render(request, 'circuits/circuit.html', { return {
'object': circuit,
'termination_a': termination_a, 'termination_a': termination_a,
'termination_z': termination_z, 'termination_z': termination_z,
}) }
class CircuitEditView(generic.ObjectEditView): class CircuitEditView(generic.ObjectEditView):

View File

@ -152,16 +152,14 @@ class SiteListView(generic.ObjectListView):
class SiteView(generic.ObjectView): class SiteView(generic.ObjectView):
queryset = Site.objects.prefetch_related('region', 'tenant__group') queryset = Site.objects.prefetch_related('region', 'tenant__group')
def get(self, request, slug): def get_extra_context(self, request, instance):
site = get_object_or_404(self.queryset, slug=slug)
stats = { stats = {
'rack_count': Rack.objects.restrict(request.user, 'view').filter(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=site).count(), 'device_count': Device.objects.restrict(request.user, 'view').filter(site=instance).count(),
'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(site=site).count(), 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(site=instance).count(),
'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=site).count(), 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=instance).count(),
'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=site).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=site).count(), 'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance).count(),
} }
rack_groups = RackGroup.objects.add_related_count( rack_groups = RackGroup.objects.add_related_count(
RackGroup.objects.all(), RackGroup.objects.all(),
@ -169,13 +167,12 @@ class SiteView(generic.ObjectView):
'group', 'group',
'rack_count', 'rack_count',
cumulative=True cumulative=True
).restrict(request.user, 'view').filter(site=site) ).restrict(request.user, 'view').filter(site=instance)
return render(request, 'dcim/site.html', { return {
'object': site,
'stats': stats, 'stats': stats,
'rack_groups': rack_groups, 'rack_groups': rack_groups,
}) }
class SiteEditView(generic.ObjectEditView): class SiteEditView(generic.ObjectEditView):
@ -338,36 +335,37 @@ class RackElevationListView(generic.ObjectListView):
class RackView(generic.ObjectView): class RackView(generic.ObjectView):
queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'group', 'role') queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'group', 'role')
def get(self, request, pk): def get_extra_context(self, request, instance):
rack = get_object_or_404(self.queryset, pk=pk)
# Get 0U and child devices located within the rack # Get 0U and child devices located within the rack
nonracked_devices = Device.objects.filter( nonracked_devices = Device.objects.filter(
rack=rack, rack=instance,
position__isnull=True position__isnull=True
).prefetch_related('device_type__manufacturer') ).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: if instance.group:
peer_racks = peer_racks.filter(group=rack.group) peer_racks = peer_racks.filter(group=instance.group)
else: else:
peer_racks = peer_racks.filter(group__isnull=True) peer_racks = peer_racks.filter(group__isnull=True)
next_rack = peer_racks.filter(name__gt=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=rack.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) reservations = RackReservation.objects.restrict(request.user, 'view').filter(rack=instance)
power_feeds = PowerFeed.objects.restrict(request.user, 'view').filter(rack=rack).prefetch_related('power_panel') power_feeds = PowerFeed.objects.restrict(request.user, 'view').filter(rack=instance).prefetch_related(
'power_panel'
)
return render(request, 'dcim/rack.html', { device_count = Device.objects.restrict(request.user, 'view').filter(rack=instance).count()
'object': rack,
'device_count': Device.objects.restrict(request.user, 'view').filter(rack=rack).count(), return {
'device_count': device_count,
'reservations': reservations, 'reservations': reservations,
'power_feeds': power_feeds, 'power_feeds': power_feeds,
'nonracked_devices': nonracked_devices, 'nonracked_devices': nonracked_devices,
'next_rack': next_rack, 'next_rack': next_rack,
'prev_rack': prev_rack, 'prev_rack': prev_rack,
}) }
class RackEditView(generic.ObjectEditView): class RackEditView(generic.ObjectEditView):
@ -511,42 +509,40 @@ class DeviceTypeListView(generic.ObjectListView):
class DeviceTypeView(generic.ObjectView): class DeviceTypeView(generic.ObjectView):
queryset = DeviceType.objects.prefetch_related('manufacturer') queryset = DeviceType.objects.prefetch_related('manufacturer')
def get(self, request, pk): def get_extra_context(self, request, instance):
instance_count = Device.objects.restrict(request.user).filter(device_type=instance).count()
devicetype = get_object_or_404(self.queryset, pk=pk)
instance_count = Device.objects.restrict(request.user).filter(device_type=devicetype).count()
# Component tables # Component tables
consoleport_table = tables.ConsolePortTemplateTable( 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 orderable=False
) )
consoleserverport_table = tables.ConsoleServerPortTemplateTable( 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 orderable=False
) )
powerport_table = tables.PowerPortTemplateTable( 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 orderable=False
) )
poweroutlet_table = tables.PowerOutletTemplateTable( 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 orderable=False
) )
interface_table = tables.InterfaceTemplateTable( 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 orderable=False
) )
front_port_table = tables.FrontPortTemplateTable( 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 orderable=False
) )
rear_port_table = tables.RearPortTemplateTable( 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 orderable=False
) )
devicebay_table = tables.DeviceBayTemplateTable( 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 orderable=False
) )
if request.user.has_perm('dcim.change_devicetype'): if request.user.has_perm('dcim.change_devicetype'):
@ -559,8 +555,7 @@ class DeviceTypeView(generic.ObjectView):
rear_port_table.columns.show('pk') rear_port_table.columns.show('pk')
devicebay_table.columns.show('pk') devicebay_table.columns.show('pk')
return render(request, 'dcim/devicetype.html', { return {
'object': devicetype,
'instance_count': instance_count, 'instance_count': instance_count,
'consoleport_table': consoleport_table, 'consoleport_table': consoleport_table,
'consoleserverport_table': consoleserverport_table, 'consoleserverport_table': consoleserverport_table,
@ -570,7 +565,7 @@ class DeviceTypeView(generic.ObjectView):
'front_port_table': front_port_table, 'front_port_table': front_port_table,
'rear_port_table': rear_port_table, 'rear_port_table': rear_port_table,
'devicebay_table': devicebay_table, 'devicebay_table': devicebay_table,
}) }
class DeviceTypeEditView(generic.ObjectEditView): class DeviceTypeEditView(generic.ObjectEditView):
@ -986,51 +981,47 @@ class DeviceView(generic.ObjectView):
queryset = Device.objects.prefetch_related( queryset = Device.objects.prefetch_related(
'site__region', 'rack__group', 'tenant__group', 'device_role', 'platform', 'primary_ip4', 'primary_ip6' 'site__region', 'rack__group', 'tenant__group', 'device_role', 'platform', 'primary_ip4', 'primary_ip6'
) )
template_name = 'dcim/device/device.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk)
# VirtualChassis members # 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( vc_members = Device.objects.restrict(request.user, 'view').filter(
virtual_chassis=device.virtual_chassis virtual_chassis=instance.virtual_chassis
).order_by('vc_position') ).order_by('vc_position')
else: else:
vc_members = [] vc_members = []
# Services # Services
services = Service.objects.restrict(request.user, 'view').filter(device=device) services = Service.objects.restrict(request.user, 'view').filter(device=instance)
# Secrets # 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. # 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( 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( ).exclude(
pk=device.pk pk=instance.pk
).prefetch_related( ).prefetch_related(
'rack', 'device_type__manufacturer' 'rack', 'device_type__manufacturer'
)[:10] )[:10]
return render(request, 'dcim/device/device.html', { return {
'object': device,
'services': services, 'services': services,
'secrets': secrets, 'secrets': secrets,
'vc_members': vc_members, 'vc_members': vc_members,
'related_devices': related_devices, 'related_devices': related_devices,
'active_tab': 'device', 'active_tab': 'device',
}) }
class DeviceConsolePortsView(generic.ObjectView): class DeviceConsolePortsView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/consoleports.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk) consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related(
consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'cable', '_path__destination', 'cable', '_path__destination',
) )
consoleport_table = tables.DeviceConsolePortTable( 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'): if request.user.has_perm('dcim.change_consoleport') or request.user.has_perm('dcim.delete_consoleport'):
consoleport_table.columns.show('pk') consoleport_table.columns.show('pk')
return render(request, 'dcim/device/consoleports.html', { return {
'object': device,
'consoleport_table': consoleport_table, 'consoleport_table': consoleport_table,
'active_tab': 'console-ports', 'active_tab': 'console-ports',
}) }
class DeviceConsoleServerPortsView(generic.ObjectView): class DeviceConsoleServerPortsView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/consoleserverports.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk)
consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter( consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter(
device=device device=instance
).prefetch_related( ).prefetch_related(
'cable', '_path__destination', 'cable', '_path__destination',
) )
@ -1068,20 +1057,18 @@ class DeviceConsoleServerPortsView(generic.ObjectView):
request.user.has_perm('dcim.delete_consoleserverport'): request.user.has_perm('dcim.delete_consoleserverport'):
consoleserverport_table.columns.show('pk') consoleserverport_table.columns.show('pk')
return render(request, 'dcim/device/consoleserverports.html', { return {
'object': device,
'consoleserverport_table': consoleserverport_table, 'consoleserverport_table': consoleserverport_table,
'active_tab': 'console-server-ports', 'active_tab': 'console-server-ports',
}) }
class DevicePowerPortsView(generic.ObjectView): class DevicePowerPortsView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/powerports.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk) powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related(
powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'cable', '_path__destination', 'cable', '_path__destination',
) )
powerport_table = tables.DevicePowerPortTable( 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'): if request.user.has_perm('dcim.change_powerport') or request.user.has_perm('dcim.delete_powerport'):
powerport_table.columns.show('pk') powerport_table.columns.show('pk')
return render(request, 'dcim/device/powerports.html', { return {
'object': device,
'powerport_table': powerport_table, 'powerport_table': powerport_table,
'active_tab': 'power-ports', 'active_tab': 'power-ports',
}) }
class DevicePowerOutletsView(generic.ObjectView): class DevicePowerOutletsView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/poweroutlets.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk) poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related(
poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'cable', 'power_port', '_path__destination', 'cable', 'power_port', '_path__destination',
) )
poweroutlet_table = tables.DevicePowerOutletTable( 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'): if request.user.has_perm('dcim.change_poweroutlet') or request.user.has_perm('dcim.delete_poweroutlet'):
poweroutlet_table.columns.show('pk') poweroutlet_table.columns.show('pk')
return render(request, 'dcim/device/poweroutlets.html', { return {
'object': device,
'poweroutlet_table': poweroutlet_table, 'poweroutlet_table': poweroutlet_table,
'active_tab': 'power-outlets', 'active_tab': 'power-outlets',
}) }
class DeviceInterfacesView(generic.ObjectView): class DeviceInterfacesView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/interfaces.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk) interfaces = instance.vc_interfaces.restrict(request.user, 'view').prefetch_related(
interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related(
Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)), Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)),
Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)),
'lag', 'cable', '_path__destination', 'tags', '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'): if request.user.has_perm('dcim.change_interface') or request.user.has_perm('dcim.delete_interface'):
interface_table.columns.show('pk') interface_table.columns.show('pk')
return render(request, 'dcim/device/interfaces.html', { return {
'object': device,
'interface_table': interface_table, 'interface_table': interface_table,
'active_tab': 'interfaces', 'active_tab': 'interfaces',
}) }
class DeviceFrontPortsView(generic.ObjectView): class DeviceFrontPortsView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/frontports.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk) frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related(
frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'rear_port', 'cable', 'rear_port', 'cable',
) )
frontport_table = tables.DeviceFrontPortTable( 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'): if request.user.has_perm('dcim.change_frontport') or request.user.has_perm('dcim.delete_frontport'):
frontport_table.columns.show('pk') frontport_table.columns.show('pk')
return render(request, 'dcim/device/frontports.html', { return {
'object': device,
'frontport_table': frontport_table, 'frontport_table': frontport_table,
'active_tab': 'front-ports', 'active_tab': 'front-ports',
}) }
class DeviceRearPortsView(generic.ObjectView): class DeviceRearPortsView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/rearports.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk) rearports = RearPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related('cable')
rearports = RearPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related('cable')
rearport_table = tables.DeviceRearPortTable( rearport_table = tables.DeviceRearPortTable(
data=rearports, data=rearports,
user=request.user, 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'): if request.user.has_perm('dcim.change_rearport') or request.user.has_perm('dcim.delete_rearport'):
rearport_table.columns.show('pk') rearport_table.columns.show('pk')
return render(request, 'dcim/device/rearports.html', { return {
'object': device,
'rearport_table': rearport_table, 'rearport_table': rearport_table,
'active_tab': 'rear-ports', 'active_tab': 'rear-ports',
}) }
class DeviceDeviceBaysView(generic.ObjectView): class DeviceDeviceBaysView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/devicebays.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk) devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related(
devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'installed_device__device_type__manufacturer', 'installed_device__device_type__manufacturer',
) )
devicebay_table = tables.DeviceDeviceBayTable( 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'): if request.user.has_perm('dcim.change_devicebay') or request.user.has_perm('dcim.delete_devicebay'):
devicebay_table.columns.show('pk') devicebay_table.columns.show('pk')
return render(request, 'dcim/device/devicebays.html', { return {
'object': device,
'devicebay_table': devicebay_table, 'devicebay_table': devicebay_table,
'active_tab': 'device-bays', 'active_tab': 'device-bays',
}) }
class DeviceInventoryView(generic.ObjectView): class DeviceInventoryView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/inventory.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
device = get_object_or_404(self.queryset, pk=pk)
inventoryitems = InventoryItem.objects.restrict(request.user, 'view').filter( inventoryitems = InventoryItem.objects.restrict(request.user, 'view').filter(
device=device device=instance
).prefetch_related('manufacturer') ).prefetch_related('manufacturer')
inventoryitem_table = tables.DeviceInventoryItemTable( inventoryitem_table = tables.DeviceInventoryItemTable(
data=inventoryitems, 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'): if request.user.has_perm('dcim.change_inventoryitem') or request.user.has_perm('dcim.delete_inventoryitem'):
inventoryitem_table.columns.show('pk') inventoryitem_table.columns.show('pk')
return render(request, 'dcim/device/inventory.html', { return {
'object': device,
'inventoryitem_table': inventoryitem_table, 'inventoryitem_table': inventoryitem_table,
'active_tab': 'inventory', 'active_tab': 'inventory',
}) }
class DeviceStatusView(generic.ObjectView): class DeviceStatusView(generic.ObjectView):
@ -1248,7 +1222,7 @@ class DeviceStatusView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/status.html' template_name = 'dcim/device/status.html'
def get_extra_context(self): def get_extra_context(self, request, instance):
return { return {
'active_tab': 'status', 'active_tab': 'status',
} }
@ -1257,19 +1231,19 @@ class DeviceStatusView(generic.ObjectView):
class DeviceLLDPNeighborsView(generic.ObjectView): class DeviceLLDPNeighborsView(generic.ObjectView):
additional_permissions = ['dcim.napalm_read_device'] additional_permissions = ['dcim.napalm_read_device']
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/lldp_neighbors.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
interfaces = instance.vc_interfaces.restrict(request.user, 'view').prefetch_related(
device = get_object_or_404(self.queryset, pk=pk) '_path__destination'
interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related('_path__destination').exclude( ).exclude(
type__in=NONCONNECTABLE_IFACE_TYPES type__in=NONCONNECTABLE_IFACE_TYPES
) )
return render(request, 'dcim/device/lldp_neighbors.html', { return {
'object': device,
'interfaces': interfaces, 'interfaces': interfaces,
'active_tab': 'lldp-neighbors', 'active_tab': 'lldp-neighbors',
}) }
class DeviceConfigView(generic.ObjectView): class DeviceConfigView(generic.ObjectView):
@ -1277,7 +1251,7 @@ class DeviceConfigView(generic.ObjectView):
queryset = Device.objects.all() queryset = Device.objects.all()
template_name = 'dcim/device/config.html' template_name = 'dcim/device/config.html'
def get_extra_context(self): def get_extra_context(self, request, instance):
return { return {
'active_tab': 'config', 'active_tab': 'config',
} }
@ -1595,35 +1569,31 @@ class InterfaceListView(generic.ObjectListView):
class InterfaceView(generic.ObjectView): class InterfaceView(generic.ObjectView):
queryset = Interface.objects.all() queryset = Interface.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
interface = get_object_or_404(self.queryset, pk=pk)
# Get assigned IP addresses # Get assigned IP addresses
ipaddress_table = InterfaceIPAddressTable( 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 orderable=False
) )
# Get assigned VLANs and annotate whether each is tagged or untagged # Get assigned VLANs and annotate whether each is tagged or untagged
vlans = [] vlans = []
if interface.untagged_vlan is not None: if instance.untagged_vlan is not None:
vlans.append(interface.untagged_vlan) vlans.append(instance.untagged_vlan)
vlans[0].tagged = False 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 vlan.tagged = True
vlans.append(vlan) vlans.append(vlan)
vlan_table = InterfaceVLANTable( vlan_table = InterfaceVLANTable(
interface=interface, interface=instance,
data=vlans, data=vlans,
orderable=False orderable=False
) )
return render(request, 'dcim/interface.html', { return {
'object': interface,
'ipaddress_table': ipaddress_table, 'ipaddress_table': ipaddress_table,
'vlan_table': vlan_table, 'vlan_table': vlan_table,
}) }
class InterfaceCreateView(generic.ComponentCreateView): class InterfaceCreateView(generic.ComponentCreateView):
@ -2090,6 +2060,7 @@ class PathTraceView(generic.ObjectView):
Trace a cable path beginning from the given path endpoint (origin). Trace a cable path beginning from the given path endpoint (origin).
""" """
additional_permissions = ['dcim.view_cable'] additional_permissions = ['dcim.view_cable']
template_name = 'dcim/cable_trace.html'
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
model = kwargs.pop('model') model = kwargs.pop('model')
@ -2097,13 +2068,12 @@ class PathTraceView(generic.ObjectView):
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get(self, request, pk): def get_extra_context(self, request, instance):
obj = get_object_or_404(self.queryset, pk=pk)
related_paths = [] related_paths = []
# If tracing a PathEndpoint, locate the CablePath (if one exists) by its origin # If tracing a PathEndpoint, locate the CablePath (if one exists) by its origin
if isinstance(obj, PathEndpoint): if isinstance(instance, PathEndpoint):
path = obj._path path = instance._path
# Otherwise, find all CablePaths which traverse the specified object # Otherwise, find all CablePaths which traverse the specified object
else: else:
@ -2118,12 +2088,11 @@ class PathTraceView(generic.ObjectView):
else: else:
path = related_paths.first() path = related_paths.first()
return render(request, 'dcim/cable_trace.html', { return {
'object': obj,
'path': path, 'path': path,
'related_paths': related_paths, 'related_paths': related_paths,
'total_length': path.get_total_length() if path else None, 'total_length': path.get_total_length() if path else None,
}) }
class CableCreateView(generic.ObjectEditView): class CableCreateView(generic.ObjectEditView):
@ -2330,14 +2299,12 @@ class VirtualChassisListView(generic.ObjectListView):
class VirtualChassisView(generic.ObjectView): class VirtualChassisView(generic.ObjectView):
queryset = VirtualChassis.objects.all() queryset = VirtualChassis.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
virtualchassis = get_object_or_404(self.queryset, pk=pk) members = Device.objects.restrict(request.user).filter(virtual_chassis=instance)
members = Device.objects.restrict(request.user).filter(virtual_chassis=virtualchassis)
return render(request, 'dcim/virtualchassis.html', { return {
'object': virtualchassis,
'members': members, 'members': members,
}) }
class VirtualChassisCreateView(generic.ObjectEditView): class VirtualChassisCreateView(generic.ObjectEditView):
@ -2560,20 +2527,17 @@ class PowerPanelListView(generic.ObjectListView):
class PowerPanelView(generic.ObjectView): class PowerPanelView(generic.ObjectView):
queryset = PowerPanel.objects.prefetch_related('site', 'rack_group') queryset = PowerPanel.objects.prefetch_related('site', 'rack_group')
def get(self, request, pk): def get_extra_context(self, request, instance):
power_feeds = PowerFeed.objects.restrict(request.user).filter(power_panel=instance).prefetch_related('rack')
powerpanel = get_object_or_404(self.queryset, pk=pk)
power_feeds = PowerFeed.objects.restrict(request.user).filter(power_panel=powerpanel).prefetch_related('rack')
powerfeed_table = tables.PowerFeedTable( powerfeed_table = tables.PowerFeedTable(
data=power_feeds, data=power_feeds,
orderable=False orderable=False
) )
powerfeed_table.exclude = ['power_panel'] powerfeed_table.exclude = ['power_panel']
return render(request, 'dcim/powerpanel.html', { return {
'object': powerpanel,
'powerfeed_table': powerfeed_table, 'powerfeed_table': powerfeed_table,
}) }
class PowerPanelEditView(generic.ObjectEditView): class PowerPanelEditView(generic.ObjectEditView):

View File

@ -83,21 +83,7 @@ class ConfigContextListView(generic.ObjectListView):
class ConfigContextView(generic.ObjectView): class ConfigContextView(generic.ObjectView):
queryset = ConfigContext.objects.all() queryset = ConfigContext.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
# 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)
# Determine user's preferred output format # Determine user's preferred output format
if request.GET.get('format') in ['json', 'yaml']: if request.GET.get('format') in ['json', 'yaml']:
format = request.GET.get('format') format = request.GET.get('format')
@ -108,10 +94,9 @@ class ConfigContextView(generic.ObjectView):
else: else:
format = 'json' format = 'json'
return render(request, 'extras/configcontext.html', { return {
'object': configcontext,
'format': format, 'format': format,
}) }
class ConfigContextEditView(generic.ObjectEditView): class ConfigContextEditView(generic.ObjectEditView):
@ -138,12 +123,10 @@ class ConfigContextBulkDeleteView(generic.BulkDeleteView):
class ObjectConfigContextView(generic.ObjectView): class ObjectConfigContextView(generic.ObjectView):
base_template = None base_template = None
template_name = 'extras/object_configcontext.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
source_contexts = ConfigContext.objects.restrict(request.user, 'view').get_for_object(instance)
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
# Determine user's preferred output format # Determine user's preferred output format
if request.GET.get('format') in ['json', 'yaml']: if request.GET.get('format') in ['json', 'yaml']:
@ -155,14 +138,13 @@ class ObjectConfigContextView(generic.ObjectView):
else: else:
format = 'json' format = 'json'
return render(request, 'extras/object_configcontext.html', { return {
'object': obj, 'rendered_context': instance.get_config_context(),
'rendered_context': obj.get_config_context(),
'source_contexts': source_contexts, 'source_contexts': source_contexts,
'format': format, 'format': format,
'base_template': self.base_template, 'base_template': self.base_template,
'active_tab': 'config-context', 'active_tab': 'config-context',
}) }
# #
@ -181,14 +163,11 @@ class ObjectChangeListView(generic.ObjectListView):
class ObjectChangeView(generic.ObjectView): class ObjectChangeView(generic.ObjectView):
queryset = ObjectChange.objects.all() queryset = ObjectChange.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
objectchange = get_object_or_404(self.queryset, pk=pk)
related_changes = ObjectChange.objects.restrict(request.user, 'view').filter( related_changes = ObjectChange.objects.restrict(request.user, 'view').filter(
request_id=objectchange.request_id request_id=instance.request_id
).exclude( ).exclude(
pk=objectchange.pk pk=instance.pk
) )
related_changes_table = tables.ObjectChangeTable( related_changes_table = tables.ObjectChangeTable(
data=related_changes[:50], data=related_changes[:50],
@ -196,33 +175,32 @@ class ObjectChangeView(generic.ObjectView):
) )
objectchanges = ObjectChange.objects.restrict(request.user, 'view').filter( objectchanges = ObjectChange.objects.restrict(request.user, 'view').filter(
changed_object_type=objectchange.changed_object_type, changed_object_type=instance.changed_object_type,
changed_object_id=objectchange.changed_object_id, changed_object_id=instance.changed_object_id,
) )
next_change = objectchanges.filter(time__gt=objectchange.time).order_by('time').first() next_change = objectchanges.filter(time__gt=instance.time).order_by('time').first()
prev_change = objectchanges.filter(time__lt=objectchange.time).order_by('-time').first() prev_change = objectchanges.filter(time__lt=instance.time).order_by('-time').first()
if prev_change: if prev_change:
diff_added = shallow_compare_dict( diff_added = shallow_compare_dict(
prev_change.object_data, prev_change.object_data,
objectchange.object_data, instance.object_data,
exclude=['last_updated'], exclude=['last_updated'],
) )
diff_removed = {x: prev_change.object_data.get(x) for x in diff_added} diff_removed = {x: prev_change.object_data.get(x) for x in diff_added}
else: else:
# No previous change; this is the initial change that added the object # 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', { return {
'object': objectchange,
'diff_added': diff_added, 'diff_added': diff_added,
'diff_removed': diff_removed, 'diff_removed': diff_removed,
'next_change': next_change, 'next_change': next_change,
'prev_change': prev_change, 'prev_change': prev_change,
'related_changes_table': related_changes_table, 'related_changes_table': related_changes_table,
'related_changes_count': related_changes.count() 'related_changes_count': related_changes.count()
}) }
class ObjectChangeLogView(View): class ObjectChangeLogView(View):

View File

@ -28,26 +28,23 @@ class VRFListView(generic.ObjectListView):
class VRFView(generic.ObjectView): class VRFView(generic.ObjectView):
queryset = VRF.objects.all() queryset = VRF.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=instance).count()
vrf = get_object_or_404(self.queryset, pk=pk)
prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=vrf).count()
import_targets_table = tables.RouteTargetTable( import_targets_table = tables.RouteTargetTable(
vrf.import_targets.prefetch_related('tenant'), instance.import_targets.prefetch_related('tenant'),
orderable=False orderable=False
) )
export_targets_table = tables.RouteTargetTable( export_targets_table = tables.RouteTargetTable(
vrf.export_targets.prefetch_related('tenant'), instance.export_targets.prefetch_related('tenant'),
orderable=False orderable=False
) )
return render(request, 'ipam/vrf.html', { return {
'object': vrf,
'prefix_count': prefix_count, 'prefix_count': prefix_count,
'import_targets_table': import_targets_table, 'import_targets_table': import_targets_table,
'export_targets_table': export_targets_table, 'export_targets_table': export_targets_table,
}) }
class VRFEditView(generic.ObjectEditView): class VRFEditView(generic.ObjectEditView):
@ -93,23 +90,20 @@ class RouteTargetListView(generic.ObjectListView):
class RouteTargetView(generic.ObjectView): class RouteTargetView(generic.ObjectView):
queryset = RouteTarget.objects.all() queryset = RouteTarget.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
routetarget = get_object_or_404(self.queryset, pk=pk)
importing_vrfs_table = tables.VRFTable( importing_vrfs_table = tables.VRFTable(
routetarget.importing_vrfs.prefetch_related('tenant'), instance.importing_vrfs.prefetch_related('tenant'),
orderable=False orderable=False
) )
exporting_vrfs_table = tables.VRFTable( exporting_vrfs_table = tables.VRFTable(
routetarget.exporting_vrfs.prefetch_related('tenant'), instance.exporting_vrfs.prefetch_related('tenant'),
orderable=False orderable=False
) )
return render(request, 'ipam/routetarget.html', { return {
'object': routetarget,
'importing_vrfs_table': importing_vrfs_table, 'importing_vrfs_table': importing_vrfs_table,
'exporting_vrfs_table': exporting_vrfs_table, 'exporting_vrfs_table': exporting_vrfs_table,
}) }
class RouteTargetEditView(generic.ObjectEditView): class RouteTargetEditView(generic.ObjectEditView):
@ -206,13 +200,10 @@ class AggregateListView(generic.ObjectListView):
class AggregateView(generic.ObjectView): class AggregateView(generic.ObjectView):
queryset = Aggregate.objects.all() queryset = Aggregate.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
aggregate = get_object_or_404(self.queryset, pk=pk)
# Find all child prefixes contained by this aggregate # Find all child prefixes contained by this aggregate
child_prefixes = Prefix.objects.restrict(request.user, 'view').filter( 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( ).prefetch_related(
'site', 'role' 'site', 'role'
).order_by( ).order_by(
@ -221,7 +212,7 @@ class AggregateView(generic.ObjectView):
# Add available prefixes to the table if requested # Add available prefixes to the table if requested
if request.GET.get('show_available', 'true') == 'true': 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) prefix_table = tables.PrefixDetailTable(child_prefixes)
if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): 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'), 'delete': request.user.has_perm('ipam.delete_prefix'),
} }
return render(request, 'ipam/aggregate.html', { return {
'object': aggregate,
'prefix_table': prefix_table, 'prefix_table': prefix_table,
'permissions': permissions, 'permissions': permissions,
'show_available': request.GET.get('show_available', 'true') == 'true', 'show_available': request.GET.get('show_available', 'true') == 'true',
}) }
class AggregateEditView(generic.ObjectEditView): class AggregateEditView(generic.ObjectEditView):
@ -324,22 +314,19 @@ class PrefixListView(generic.ObjectListView):
class PrefixView(generic.ObjectView): class PrefixView(generic.ObjectView):
queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role') queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role')
def get(self, request, pk): def get_extra_context(self, request, instance):
prefix = get_object_or_404(self.queryset, pk=pk)
try: try:
aggregate = Aggregate.objects.restrict(request.user, 'view').get( 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: except Aggregate.DoesNotExist:
aggregate = None aggregate = None
# Parent prefixes table # Parent prefixes table
parent_prefixes = Prefix.objects.restrict(request.user, 'view').filter( 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( ).filter(
prefix__net_contains=str(prefix.prefix) prefix__net_contains=str(instance.prefix)
).prefetch_related( ).prefetch_related(
'site', 'role' 'site', 'role'
).annotate_tree() ).annotate_tree()
@ -348,38 +335,35 @@ class PrefixView(generic.ObjectView):
# Duplicate prefixes table # Duplicate prefixes table
duplicate_prefixes = Prefix.objects.restrict(request.user, 'view').filter( duplicate_prefixes = Prefix.objects.restrict(request.user, 'view').filter(
vrf=prefix.vrf, prefix=str(prefix.prefix) vrf=instance.vrf, prefix=str(instance.prefix)
).exclude( ).exclude(
pk=prefix.pk pk=instance.pk
).prefetch_related( ).prefetch_related(
'site', 'role' 'site', 'role'
) )
duplicate_prefix_table = tables.PrefixTable(list(duplicate_prefixes), orderable=False) duplicate_prefix_table = tables.PrefixTable(list(duplicate_prefixes), orderable=False)
duplicate_prefix_table.exclude = ('vrf',) duplicate_prefix_table.exclude = ('vrf',)
return render(request, 'ipam/prefix.html', { return {
'object': prefix,
'aggregate': aggregate, 'aggregate': aggregate,
'parent_prefix_table': parent_prefix_table, 'parent_prefix_table': parent_prefix_table,
'duplicate_prefix_table': duplicate_prefix_table, 'duplicate_prefix_table': duplicate_prefix_table,
}) }
class PrefixPrefixesView(generic.ObjectView): class PrefixPrefixesView(generic.ObjectView):
queryset = Prefix.objects.all() queryset = Prefix.objects.all()
template_name = 'ipam/prefix_prefixes.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
prefix = get_object_or_404(self.queryset, pk=pk)
# Child prefixes table # 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', 'site', 'vlan', 'role',
).annotate_tree() ).annotate_tree()
# Add available prefixes to the table if requested # Add available prefixes to the table if requested
if child_prefixes and request.GET.get('show_available', 'true') == 'true': 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) prefix_table = tables.PrefixDetailTable(child_prefixes)
if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): 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'), 'delete': request.user.has_perm('ipam.delete_prefix'),
} }
return render(request, 'ipam/prefix_prefixes.html', { bulk_querystring = 'vrf_id={}&within={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix)
'object': prefix,
'first_available_prefix': prefix.get_first_available_prefix(), return {
'first_available_prefix': instance.get_first_available_prefix(),
'prefix_table': prefix_table, 'prefix_table': prefix_table,
'permissions': permissions, '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', 'active_tab': 'prefixes',
'show_available': request.GET.get('show_available', 'true') == 'true', 'show_available': request.GET.get('show_available', 'true') == 'true',
}) }
class PrefixIPAddressesView(generic.ObjectView): class PrefixIPAddressesView(generic.ObjectView):
queryset = Prefix.objects.all() queryset = Prefix.objects.all()
template_name = 'ipam/prefix_ipaddresses.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
prefix = get_object_or_404(self.queryset, pk=pk)
# Find all IPAddresses belonging to this Prefix # 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' 'vrf', 'primary_ip4_for', 'primary_ip6_for'
) )
# Add available IP addresses to the table if requested # Add available IP addresses to the table if requested
if request.GET.get('show_available', 'true') == 'true': 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) ip_table = tables.IPAddressTable(ipaddresses)
if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'): 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'), 'delete': request.user.has_perm('ipam.delete_ipaddress'),
} }
return render(request, 'ipam/prefix_ipaddresses.html', { bulk_querystring = 'vrf_id={}&parent={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix)
'object': prefix,
'first_available_ip': prefix.get_first_available_ip(), return {
'first_available_ip': instance.get_first_available_ip(),
'ip_table': ip_table, 'ip_table': ip_table,
'permissions': permissions, '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', 'active_tab': 'ip-addresses',
'show_available': request.GET.get('show_available', 'true') == 'true', 'show_available': request.GET.get('show_available', 'true') == 'true',
}) }
class PrefixEditView(generic.ObjectEditView): class PrefixEditView(generic.ObjectEditView):
@ -497,13 +481,11 @@ class IPAddressListView(generic.ObjectListView):
class IPAddressView(generic.ObjectView): class IPAddressView(generic.ObjectView):
queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant') queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant')
def get(self, request, pk): def get_extra_context(self, request, instance):
ipaddress = get_object_or_404(self.queryset, pk=pk)
# Parent prefixes table # Parent prefixes table
parent_prefixes = Prefix.objects.restrict(request.user, 'view').filter( 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( ).prefetch_related(
'site', 'role' 'site', 'role'
) )
@ -512,23 +494,24 @@ class IPAddressView(generic.ObjectView):
# Duplicate IPs table # Duplicate IPs table
duplicate_ips = IPAddress.objects.restrict(request.user, 'view').filter( duplicate_ips = IPAddress.objects.restrict(request.user, 'view').filter(
vrf=ipaddress.vrf, address=str(ipaddress.address) vrf=instance.vrf,
address=str(instance.address)
).exclude( ).exclude(
pk=ipaddress.pk pk=instance.pk
).prefetch_related( ).prefetch_related(
'nat_inside' 'nat_inside'
) )
# Exclude anycast IPs if this IP is anycast # 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) duplicate_ips = duplicate_ips.exclude(role=IPAddressRoleChoices.ROLE_ANYCAST)
# Limit to a maximum of 10 duplicates displayed here # Limit to a maximum of 10 duplicates displayed here
duplicate_ips_table = tables.IPAddressTable(duplicate_ips[:10], orderable=False) duplicate_ips_table = tables.IPAddressTable(duplicate_ips[:10], orderable=False)
# Related IP table # Related IP table
related_ips = IPAddress.objects.restrict(request.user, 'view').exclude( related_ips = IPAddress.objects.restrict(request.user, 'view').exclude(
address=str(ipaddress.address) address=str(instance.address)
).filter( ).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) related_ips_table = tables.IPAddressTable(related_ips, orderable=False)
@ -538,13 +521,12 @@ class IPAddressView(generic.ObjectView):
} }
RequestConfig(request, paginate).configure(related_ips_table) RequestConfig(request, paginate).configure(related_ips_table)
return render(request, 'ipam/ipaddress.html', { return {
'object': ipaddress,
'parent_prefixes_table': parent_prefixes_table, 'parent_prefixes_table': parent_prefixes_table,
'duplicate_ips_table': duplicate_ips_table, 'duplicate_ips_table': duplicate_ips_table,
'more_duplicate_ips': duplicate_ips.count() > 10, 'more_duplicate_ips': duplicate_ips.count() > 10,
'related_ips_table': related_ips_table, 'related_ips_table': related_ips_table,
}) }
class IPAddressEditView(generic.ObjectEditView): class IPAddressEditView(generic.ObjectEditView):
@ -569,6 +551,7 @@ class IPAddressEditView(generic.ObjectEditView):
return obj return obj
# TODO: Standardize or remove this view
class IPAddressAssignView(generic.ObjectView): class IPAddressAssignView(generic.ObjectView):
""" """
Search for IPAddresses to be assigned to an Interface. Search for IPAddresses to be assigned to an Interface.
@ -678,14 +661,13 @@ class VLANGroupBulkDeleteView(generic.BulkDeleteView):
class VLANGroupVLANsView(generic.ObjectView): class VLANGroupVLANsView(generic.ObjectView):
queryset = VLANGroup.objects.all() queryset = VLANGroup.objects.all()
template_name = 'ipam/vlangroup_vlans.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
vlan_group = get_object_or_404(self.queryset, pk=pk) vlans = VLAN.objects.restrict(request.user, 'view').filter(group=instance).prefetch_related(
vlans = VLAN.objects.restrict(request.user, 'view').filter(group_id=pk).prefetch_related(
Prefetch('prefixes', queryset=Prefix.objects.restrict(request.user)) 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) vlan_table = tables.VLANDetailTable(vlans)
if request.user.has_perm('ipam.change_vlan') or request.user.has_perm('ipam.delete_vlan'): 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'), 'delete': request.user.has_perm('ipam.delete_vlan'),
} }
return render(request, 'ipam/vlangroup_vlans.html', { return {
'vlan_group': vlan_group, 'first_available_vlan': instance.get_next_available_vid(),
'first_available_vlan': vlan_group.get_next_available_vid(), 'bulk_querystring': f'group_id={instance.pk}',
'bulk_querystring': 'group_id={}'.format(vlan_group.pk),
'vlan_table': vlan_table, 'vlan_table': vlan_table,
'permissions': permissions, 'permissions': permissions,
}) }
# #
@ -729,27 +710,24 @@ class VLANListView(generic.ObjectListView):
class VLANView(generic.ObjectView): class VLANView(generic.ObjectView):
queryset = VLAN.objects.prefetch_related('site__region', 'tenant__group', 'role') queryset = VLAN.objects.prefetch_related('site__region', 'tenant__group', 'role')
def get(self, request, pk): def get_extra_context(self, request, instance):
prefixes = Prefix.objects.restrict(request.user, 'view').filter(vlan=instance).prefetch_related(
vlan = get_object_or_404(self.queryset, pk=pk)
prefixes = Prefix.objects.restrict(request.user, 'view').filter(vlan=vlan).prefetch_related(
'vrf', 'site', 'role' 'vrf', 'site', 'role'
) )
prefix_table = tables.PrefixTable(list(prefixes), orderable=False) prefix_table = tables.PrefixTable(list(prefixes), orderable=False)
prefix_table.exclude = ('vlan',) prefix_table.exclude = ('vlan',)
return render(request, 'ipam/vlan.html', { return {
'object': vlan,
'prefix_table': prefix_table, 'prefix_table': prefix_table,
}) }
class VLANInterfacesView(generic.ObjectView): class VLANInterfacesView(generic.ObjectView):
queryset = VLAN.objects.all() queryset = VLAN.objects.all()
template_name = 'ipam/vlan_interfaces.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
vlan = get_object_or_404(self.queryset, pk=pk) interfaces = instance.get_interfaces().prefetch_related('device')
interfaces = vlan.get_interfaces().prefetch_related('device')
members_table = tables.VLANDevicesTable(interfaces) members_table = tables.VLANDevicesTable(interfaces)
paginate = { paginate = {
@ -758,19 +736,18 @@ class VLANInterfacesView(generic.ObjectView):
} }
RequestConfig(request, paginate).configure(members_table) RequestConfig(request, paginate).configure(members_table)
return render(request, 'ipam/vlan_interfaces.html', { return {
'object': vlan,
'members_table': members_table, 'members_table': members_table,
'active_tab': 'interfaces', 'active_tab': 'interfaces',
}) }
class VLANVMInterfacesView(generic.ObjectView): class VLANVMInterfacesView(generic.ObjectView):
queryset = VLAN.objects.all() queryset = VLAN.objects.all()
template_name = 'ipam/vlan_vminterfaces.html'
def get(self, request, pk): def get_extra_context(self, request, instance):
vlan = get_object_or_404(self.queryset, pk=pk) interfaces = instance.get_vminterfaces().prefetch_related('virtual_machine')
interfaces = vlan.get_vminterfaces().prefetch_related('virtual_machine')
members_table = tables.VLANVirtualMachinesTable(interfaces) members_table = tables.VLANVirtualMachinesTable(interfaces)
paginate = { paginate = {
@ -779,11 +756,10 @@ class VLANVMInterfacesView(generic.ObjectView):
} }
RequestConfig(request, paginate).configure(members_table) RequestConfig(request, paginate).configure(members_table)
return render(request, 'ipam/vlan_vminterfaces.html', { return {
'object': vlan,
'members_table': members_table, 'members_table': members_table,
'active_tab': 'vminterfaces', 'active_tab': 'vminterfaces',
}) }
class VLANEditView(generic.ObjectEditView): class VLANEditView(generic.ObjectEditView):

View File

@ -32,9 +32,11 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
""" """
Retrieve a single object for display. 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 queryset = None
template_name = None
def get_required_permission(self): def get_required_permission(self):
return get_permission_for_model(self.queryset.model, 'view') 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. 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 return self.template_name
model_opts = self.queryset.model._meta model_opts = self.queryset.model._meta
return f'{model_opts.app_label}/{model_opts.model_name}.html' 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. Return any additional context data for the template.
request: The current request
instance: The object being viewed
""" """
return {} return {}
@ -58,11 +63,11 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
""" """
Generic GET handler for accessing an object by PK or slug 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(), { return render(request, self.get_template_name(), {
'object': obj, 'object': instance,
**self.get_extra_context(), **self.get_extra_context(request, instance),
}) })

View File

@ -1,14 +1,14 @@
<div class="pull-right"> <div class="pull-right">
{% if perms.ipam.add_vlan and first_available_vlan %} {% if perms.ipam.add_vlan and first_available_vlan %}
<a href="{% url 'ipam:vlan_add' %}?vid={{ first_available_vlan }}&group={{ vlan_group.pk }}{% if vlan_group.site %}&site={{ vlan_group.site.pk }}{% endif %}" class="btn btn-success"> <a href="{% url 'ipam:vlan_add' %}?vid={{ first_available_vlan }}&group={{ object.pk }}{% if object.site %}&site={{ object.site.pk }}{% endif %}" class="btn btn-success">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add a VLAN <i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add a VLAN
</a> </a>
{% endif %} {% endif %}
{% if perms.ipam.change_vlangroup %} {% if perms.ipam.change_vlangroup %}
<a href="{% url 'ipam:vlangroup_edit' pk=vlan_group.pk %}" class="btn btn-warning"> <a href="{% url 'ipam:vlangroup_edit' pk=object.pk %}" class="btn btn-warning">
<span class="mdi mdi-pencil" aria-hidden="true"></span> <span class="mdi mdi-pencil" aria-hidden="true"></span>
Edit this VLAN Group Edit this VLAN Group
</a> </a>
{% endif %} {% endif %}
</div> </div>
<h1>{{ vlan_group }}</h1> <h1>{{ object }}</h1>

View File

@ -1,16 +1,16 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}{{ vlan_group }} - VLANs{% endblock %} {% block title %}{{ object }} - VLANs{% endblock %}
{% block content %} {% block content %}
<div class="row noprint"> <div class="row noprint">
<div class="col-sm-12 col-md-12"> <div class="col-sm-12 col-md-12">
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a href="{% url 'ipam:vlangroup_list' %}">VLAN Groups</a></li> <li><a href="{% url 'ipam:vlangroup_list' %}">VLAN Groups</a></li>
{% if vlan_group.site %} {% if object.site %}
<li><a href="{% url 'dcim:site' slug=vlan_group.site.slug %}">{{ vlan_group.site }}</a></li> <li><a href="{% url 'dcim:site' slug=object.site.slug %}">{{ object.site }}</a></li>
{% endif %} {% endif %}
<li>{{ vlan_group }}</li> <li>{{ object }}</li>
</ol> </ol>
</div> </div>
</div> </div>

View File

@ -250,7 +250,7 @@
{% endif %} {% endif %}
{% if perms.ipam.add_service %} {% if perms.ipam.add_service %}
<div class="panel-footer text-right noprint"> <div class="panel-footer text-right noprint">
<a href="{% url 'virtualization:virtualmachine_service_assign' object=object.pk %}" class="btn btn-xs btn-primary"> <a href="{% url 'virtualization:virtualmachine_service_assign' virtualmachine=object.pk %}" class="btn btn-xs btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Assign service <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Assign service
</a> </a>
</div> </div>

View File

@ -64,27 +64,24 @@ class TenantListView(generic.ObjectListView):
class TenantView(generic.ObjectView): class TenantView(generic.ObjectView):
queryset = Tenant.objects.prefetch_related('group') queryset = Tenant.objects.prefetch_related('group')
def get(self, request, slug): def get_extra_context(self, request, instance):
tenant = get_object_or_404(self.queryset, slug=slug)
stats = { stats = {
'site_count': Site.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=tenant).count(), 'rack_count': Rack.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'rackreservation_count': RackReservation.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'rackreservation_count': RackReservation.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'device_count': Device.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'device_count': Device.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'vrf_count': VRF.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'vrf_count': VRF.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'cluster_count': Cluster.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), 'cluster_count': Cluster.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
} }
return render(request, 'tenancy/tenant.html', { return {
'object': tenant,
'stats': stats, 'stats': stats,
}) }
class TenantEditView(generic.ObjectEditView): class TenantEditView(generic.ObjectEditView):

View File

@ -92,23 +92,17 @@ class ClusterListView(generic.ObjectListView):
class ClusterView(generic.ObjectView): class ClusterView(generic.ObjectView):
queryset = Cluster.objects.all() queryset = Cluster.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
self.queryset = self.queryset.prefetch_related( devices = Device.objects.restrict(request.user, 'view').filter(cluster=instance).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(
'site', 'rack', 'tenant', 'device_type__manufacturer' 'site', 'rack', 'tenant', 'device_type__manufacturer'
) )
device_table = DeviceTable(list(devices), orderable=False) device_table = DeviceTable(list(devices), orderable=False)
if request.user.has_perm('virtualization.change_cluster'): if request.user.has_perm('virtualization.change_cluster'):
device_table.columns.show('pk') device_table.columns.show('pk')
return render(request, 'virtualization/cluster.html', { return {
'object': cluster,
'device_table': device_table, 'device_table': device_table,
}) }
class ClusterEditView(generic.ObjectEditView): class ClusterEditView(generic.ObjectEditView):
@ -237,12 +231,10 @@ class VirtualMachineListView(generic.ObjectListView):
class VirtualMachineView(generic.ObjectView): class VirtualMachineView(generic.ObjectView):
queryset = VirtualMachine.objects.prefetch_related('tenant__group') queryset = VirtualMachine.objects.prefetch_related('tenant__group')
def get(self, request, pk): def get_extra_context(self, request, instance):
virtualmachine = get_object_or_404(self.queryset, pk=pk)
# Interfaces # Interfaces
vminterfaces = VMInterface.objects.restrict(request.user, 'view').filter( vminterfaces = VMInterface.objects.restrict(request.user, 'view').filter(
virtual_machine=virtualmachine virtual_machine=instance
).prefetch_related( ).prefetch_related(
Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)) Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user))
) )
@ -253,20 +245,19 @@ class VirtualMachineView(generic.ObjectView):
# Services # Services
services = Service.objects.restrict(request.user, 'view').filter( services = Service.objects.restrict(request.user, 'view').filter(
virtual_machine=virtualmachine virtual_machine=instance
).prefetch_related( ).prefetch_related(
Prefetch('ipaddresses', queryset=IPAddress.objects.restrict(request.user)) Prefetch('ipaddresses', queryset=IPAddress.objects.restrict(request.user))
) )
# Secrets # 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', { return {
'object': virtualmachine,
'vminterface_table': vminterface_table, 'vminterface_table': vminterface_table,
'services': services, 'services': services,
'secrets': secrets, 'secrets': secrets,
}) }
class VirtualMachineConfigContextView(ObjectConfigContextView): class VirtualMachineConfigContextView(ObjectConfigContextView):
@ -318,35 +309,31 @@ class VMInterfaceListView(generic.ObjectListView):
class VMInterfaceView(generic.ObjectView): class VMInterfaceView(generic.ObjectView):
queryset = VMInterface.objects.all() queryset = VMInterface.objects.all()
def get(self, request, pk): def get_extra_context(self, request, instance):
vminterface = get_object_or_404(self.queryset, pk=pk)
# Get assigned IP addresses # Get assigned IP addresses
ipaddress_table = InterfaceIPAddressTable( 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 orderable=False
) )
# Get assigned VLANs and annotate whether each is tagged or untagged # Get assigned VLANs and annotate whether each is tagged or untagged
vlans = [] vlans = []
if vminterface.untagged_vlan is not None: if instance.untagged_vlan is not None:
vlans.append(vminterface.untagged_vlan) vlans.append(instance.untagged_vlan)
vlans[0].tagged = False 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 vlan.tagged = True
vlans.append(vlan) vlans.append(vlan)
vlan_table = InterfaceVLANTable( vlan_table = InterfaceVLANTable(
interface=vminterface, interface=instance,
data=vlans, data=vlans,
orderable=False orderable=False
) )
return render(request, 'virtualization/vminterface.html', { return {
'object': vminterface,
'ipaddress_table': ipaddress_table, 'ipaddress_table': ipaddress_table,
'vlan_table': vlan_table, 'vlan_table': vlan_table,
}) }
# TODO: This should not use ComponentCreateView # TODO: This should not use ComponentCreateView