diff --git a/netbox/circuits/tables.py b/netbox/circuits/tables.py index ea17031a1..ce3368f31 100644 --- a/netbox/circuits/tables.py +++ b/netbox/circuits/tables.py @@ -2,19 +2,9 @@ import django_tables2 as tables from django_tables2.utils import Accessor from tenancy.tables import COL_TENANT -from utilities.tables import BaseTable, TagColumn, ToggleColumn +from utilities.tables import BaseTable, ButtonsColumn, TagColumn, ToggleColumn from .models import Circuit, CircuitType, Provider -CIRCUITTYPE_ACTIONS = """ - - - -{% if perms.circuit.change_circuittype %} - -{% endif %} -""" - STATUS_LABEL = """ {{ record.get_status_display }} """ @@ -53,11 +43,7 @@ class CircuitTypeTable(BaseTable): circuit_count = tables.Column( verbose_name='Circuits' ) - actions = tables.TemplateColumn( - template_code=CIRCUITTYPE_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(CircuitType, pk_field='slug') class Meta(BaseTable.Meta): model = CircuitType diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index dd6b96406..871679fc7 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -2,7 +2,9 @@ import django_tables2 as tables from django_tables2.utils import Accessor from tenancy.tables import COL_TENANT -from utilities.tables import BaseTable, BooleanColumn, ColorColumn, ColoredLabelColumn, TagColumn, ToggleColumn +from utilities.tables import ( + BaseTable, BooleanColumn, ButtonsColumn, ColorColumn, ColoredLabelColumn, TagColumn, ToggleColumn, +) from .models import ( Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, @@ -40,69 +42,16 @@ DEVICE_LINK = """ """ -REGION_ACTIONS = """ - - - -{% if perms.dcim.change_region %} - -{% endif %} -""" - -RACKGROUP_ACTIONS = """ - - - +RACKGROUP_ELEVATIONS = """ -{% if perms.dcim.change_rackgroup %} - - - -{% endif %} -""" - -RACKROLE_ACTIONS = """ - - - -{% if perms.dcim.change_rackrole %} - -{% endif %} """ RACK_DEVICE_COUNT = """ {{ value }} """ -RACKRESERVATION_ACTIONS = """ - - - -{% if perms.dcim.change_rackreservation %} - -{% endif %} -""" - -MANUFACTURER_ACTIONS = """ - - - -{% if perms.dcim.change_manufacturer %} - -{% endif %} -""" - -DEVICEROLE_ACTIONS = """ - - - -{% if perms.dcim.change_devicerole %} - -{% endif %} -""" - DEVICEROLE_DEVICE_COUNT = """ {{ value }} """ @@ -119,15 +68,6 @@ PLATFORM_VM_COUNT = """ {{ value }} """ -PLATFORM_ACTIONS = """ - - - -{% if perms.dcim.change_platform %} - -{% endif %} -""" - STATUS_LABEL = """ {{ record.get_status_display }} """ @@ -198,11 +138,7 @@ class RegionTable(BaseTable): site_count = tables.Column( verbose_name='Sites' ) - actions = tables.TemplateColumn( - template_code=REGION_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(Region) class Meta(BaseTable.Meta): model = Region @@ -260,10 +196,9 @@ class RackGroupTable(BaseTable): rack_count = tables.Column( verbose_name='Racks' ) - actions = tables.TemplateColumn( - template_code=RACKGROUP_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' + actions = ButtonsColumn( + model=RackGroup, + prepend_template=RACKGROUP_ELEVATIONS ) class Meta(BaseTable.Meta): @@ -280,11 +215,7 @@ class RackRoleTable(BaseTable): pk = ToggleColumn() rack_count = tables.Column(verbose_name='Racks') color = tables.TemplateColumn(COLOR_LABEL) - actions = tables.TemplateColumn( - template_code=RACKROLE_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(RackRole) class Meta(BaseTable.Meta): model = RackRole @@ -386,11 +317,7 @@ class RackReservationTable(BaseTable): tags = TagColumn( url_name='dcim:rackreservation_list' ) - actions = tables.TemplateColumn( - template_code=RACKRESERVATION_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(RackReservation) class Meta(BaseTable.Meta): model = RackReservation @@ -420,11 +347,7 @@ class ManufacturerTable(BaseTable): verbose_name='Platforms' ) slug = tables.Column() - actions = tables.TemplateColumn( - template_code=MANUFACTURER_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(Manufacturer, pk_field='slug') class Meta(BaseTable.Meta): model = Manufacturer @@ -609,11 +532,8 @@ class DeviceRoleTable(BaseTable): template_code=COLOR_LABEL, verbose_name='Label' ) - actions = tables.TemplateColumn( - template_code=DEVICEROLE_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + vm_role = BooleanColumn() + actions = ButtonsColumn(DeviceRole, pk_field='slug') class Meta(BaseTable.Meta): model = DeviceRole @@ -639,11 +559,7 @@ class PlatformTable(BaseTable): orderable=False, verbose_name='VMs' ) - actions = tables.TemplateColumn( - template_code=PLATFORM_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(Platform, pk_field='slug') class Meta(BaseTable.Meta): model = Platform diff --git a/netbox/extras/tables.py b/netbox/extras/tables.py index 7a78d4b19..79a529059 100644 --- a/netbox/extras/tables.py +++ b/netbox/extras/tables.py @@ -1,21 +1,9 @@ import django_tables2 as tables from django_tables2.utils import Accessor -from utilities.tables import BaseTable, BooleanColumn, ColorColumn, ToggleColumn +from utilities.tables import BaseTable, BooleanColumn, ButtonsColumn, ColorColumn, ToggleColumn from .models import ConfigContext, ObjectChange, Tag, TaggedItem -TAG_ACTIONS = """ - - - -{% if perms.taggit.change_tag %} - -{% endif %} -{% if perms.taggit.delete_tag %} - -{% endif %} -""" - TAGGED_ITEM = """ {% if value.get_absolute_url %} {{ value }} @@ -68,12 +56,8 @@ class TagTable(BaseTable): viewname='extras:tag', args=[Accessor('slug')] ) - actions = tables.TemplateColumn( - template_code=TAG_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) color = ColorColumn() + actions = ButtonsColumn(Tag, pk_field='slug') class Meta(BaseTable.Meta): model = Tag diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index f1855327b..72ac3eb45 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -3,7 +3,7 @@ from django_tables2.utils import Accessor from dcim.models import Interface from tenancy.tables import COL_TENANT -from utilities.tables import BaseTable, BooleanColumn, TagColumn, ToggleColumn +from utilities.tables import BaseTable, BooleanColumn, ButtonsColumn, TagColumn, ToggleColumn from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF RIR_UTILIZATION = """ @@ -25,15 +25,6 @@ RIR_UTILIZATION = """ """ -RIR_ACTIONS = """ - - - -{% if perms.ipam.change_rir %} - -{% endif %} -""" - UTILIZATION_GRAPH = """ {% load helpers %} {% if record.pk %}{% utilization_graph record.get_utilization %}{% else %}—{% endif %} @@ -47,15 +38,6 @@ ROLE_VLAN_COUNT = """ {{ value }} """ -ROLE_ACTIONS = """ - - - -{% if perms.ipam.change_role %} - -{% endif %} -""" - PREFIX_LINK = """ {% if record.has_children %} @@ -136,10 +118,7 @@ VLAN_ROLE_LINK = """ {% endif %} """ -VLANGROUP_ACTIONS = """ - - - +VLANGROUP_ADD_VLAN = """ {% with next_vid=record.get_next_available_vid %} {% if next_vid and perms.ipam.add_vlan %} @@ -147,9 +126,6 @@ VLANGROUP_ACTIONS = """ {% endif %} {% endwith %} -{% if perms.ipam.change_vlangroup %} - -{% endif %} """ VLAN_MEMBER_UNTAGGED = """ @@ -214,11 +190,7 @@ class RIRTable(BaseTable): aggregate_count = tables.Column( verbose_name='Aggregates' ) - actions = tables.TemplateColumn( - template_code=RIR_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(RIR, pk_field='slug') class Meta(BaseTable.Meta): model = RIR @@ -322,11 +294,7 @@ class RoleTable(BaseTable): orderable=False, verbose_name='VLANs' ) - actions = tables.TemplateColumn( - template_code=ROLE_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(Role, pk_field='slug') class Meta(BaseTable.Meta): model = Role @@ -516,10 +484,9 @@ class VLANGroupTable(BaseTable): vlan_count = tables.Column( verbose_name='VLANs' ) - actions = tables.TemplateColumn( - template_code=VLANGROUP_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' + actions = ButtonsColumn( + model=VLANGroup, + prepend_template=VLANGROUP_ADD_VLAN ) class Meta(BaseTable.Meta): diff --git a/netbox/secrets/tables.py b/netbox/secrets/tables.py index f92c9216b..f773a278f 100644 --- a/netbox/secrets/tables.py +++ b/netbox/secrets/tables.py @@ -1,17 +1,8 @@ import django_tables2 as tables -from utilities.tables import BaseTable, TagColumn, ToggleColumn +from utilities.tables import BaseTable, ButtonsColumn, TagColumn, ToggleColumn from .models import SecretRole, Secret -SECRETROLE_ACTIONS = """ - - - -{% if perms.secrets.change_secretrole %} - -{% endif %} -""" - # # Secret roles @@ -23,11 +14,7 @@ class SecretRoleTable(BaseTable): secret_count = tables.Column( verbose_name='Secrets' ) - actions = tables.TemplateColumn( - template_code=SECRETROLE_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(SecretRole, pk_field='slug') class Meta(BaseTable.Meta): model = SecretRole diff --git a/netbox/tenancy/tables.py b/netbox/tenancy/tables.py index 147a20707..dc96b839c 100644 --- a/netbox/tenancy/tables.py +++ b/netbox/tenancy/tables.py @@ -1,6 +1,6 @@ import django_tables2 as tables -from utilities.tables import BaseTable, TagColumn, ToggleColumn +from utilities.tables import BaseTable, ButtonsColumn, TagColumn, ToggleColumn from .models import Tenant, TenantGroup MPTT_LINK = """ @@ -13,15 +13,6 @@ MPTT_LINK = """ """ -TENANTGROUP_ACTIONS = """ - - - -{% if perms.tenancy.change_tenantgroup %} - -{% endif %} -""" - COL_TENANT = """ {% if record.tenant %} {{ record.tenant }} @@ -44,11 +35,7 @@ class TenantGroupTable(BaseTable): tenant_count = tables.Column( verbose_name='Tenants' ) - actions = tables.TemplateColumn( - template_code=TENANTGROUP_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(TenantGroup, pk_field='slug') class Meta(BaseTable.Meta): model = TenantGroup diff --git a/netbox/utilities/tables.py b/netbox/utilities/tables.py index 5e277e633..ec3d5dff5 100644 --- a/netbox/utilities/tables.py +++ b/netbox/utilities/tables.py @@ -123,6 +123,49 @@ class BooleanColumn(tables.Column): return mark_safe(rendered) +class ButtonsColumn(tables.TemplateColumn): + """ + Render edit, delete, and changelog buttons for an object. + + :param model: Model class to use for calculating URL view names + :param prepend_content: Additional template content to render in the column (optional) + """ + attrs = {'td': {'class': 'text-right text-nowrap noprint'}} + # Note that braces are escaped to allow for string formatting prior to template rendering + template_code = """ + + + + {{% if perms.{app_label}.change_{model_name} %}} + + + + {{% endif %}} + {{% if perms.{app_label}.delete_{model_name} %}} + + + + {{% endif %}} + """ + + def __init__(self, model, *args, pk_field='pk', prepend_template=None, **kwargs): + if prepend_template: + prepend_template = prepend_template.replace('{', '{{') + prepend_template = prepend_template.replace('}', '}}') + self.template_code = prepend_template + self.template_code + + template_code = self.template_code.format( + app_label=model._meta.app_label, + model_name=model._meta.model_name, + pk_field=pk_field + ) + + super().__init__(template_code=template_code, *args, **kwargs) + + def header(self): + return '' + + class ColorColumn(tables.Column): """ Display a color (#RRGGBB). diff --git a/netbox/virtualization/tables.py b/netbox/virtualization/tables.py index de319361c..d53572583 100644 --- a/netbox/virtualization/tables.py +++ b/netbox/virtualization/tables.py @@ -2,27 +2,9 @@ import django_tables2 as tables from django_tables2.utils import Accessor from tenancy.tables import COL_TENANT -from utilities.tables import BaseTable, ColoredLabelColumn, TagColumn, ToggleColumn +from utilities.tables import BaseTable, ButtonsColumn, ColoredLabelColumn, TagColumn, ToggleColumn from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface -CLUSTERTYPE_ACTIONS = """ - - - -{% if perms.virtualization.change_clustertype %} - -{% endif %} -""" - -CLUSTERGROUP_ACTIONS = """ - - - -{% if perms.virtualization.change_clustergroup %} - -{% endif %} -""" - VIRTUALMACHINE_STATUS = """ {{ record.get_status_display }} """ @@ -44,11 +26,7 @@ class ClusterTypeTable(BaseTable): cluster_count = tables.Column( verbose_name='Clusters' ) - actions = tables.TemplateColumn( - template_code=CLUSTERTYPE_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(ClusterType, pk_field='slug') class Meta(BaseTable.Meta): model = ClusterType @@ -66,11 +44,7 @@ class ClusterGroupTable(BaseTable): cluster_count = tables.Column( verbose_name='Clusters' ) - actions = tables.TemplateColumn( - template_code=CLUSTERGROUP_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) + actions = ButtonsColumn(ClusterGroup, pk_field='slug') class Meta(BaseTable.Meta): model = ClusterGroup