1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Replace ButtonsColumn with ActionsColumn

This commit is contained in:
jeremystretch
2022-01-10 11:17:40 -05:00
parent 8b07fbc554
commit aed23d61fc
8 changed files with 90 additions and 165 deletions

View File

@ -7,7 +7,7 @@ from dcim.models import (
) )
from tenancy.tables import TenantColumn from tenancy.tables import TenantColumn
from utilities.tables import ( from utilities.tables import (
ActionsColumn, BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn, ActionsColumn, BaseTable, BooleanColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn,
MarkdownColumn, TagColumn, TemplateColumn, ToggleColumn, MarkdownColumn, TagColumn, TemplateColumn, ToggleColumn,
) )
from .template_code import * from .template_code import *
@ -322,10 +322,8 @@ class DeviceConsolePortTable(ConsolePortTable):
order_by=Accessor('_name'), order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=ConsolePort, extra_buttons=CONSOLEPORT_BUTTONS
buttons=('edit', 'delete'),
prepend_template=CONSOLEPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -367,10 +365,8 @@ class DeviceConsoleServerPortTable(ConsoleServerPortTable):
order_by=Accessor('_name'), order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=ConsoleServerPort, extra_buttons=CONSOLESERVERPORT_BUTTONS
buttons=('edit', 'delete'),
prepend_template=CONSOLESERVERPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -412,10 +408,8 @@ class DevicePowerPortTable(PowerPortTable):
order_by=Accessor('_name'), order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=PowerPort, extra_buttons=POWERPORT_BUTTONS
buttons=('edit', 'delete'),
prepend_template=POWERPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -461,10 +455,8 @@ class DevicePowerOutletTable(PowerOutletTable):
order_by=Accessor('_name'), order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=PowerOutlet, extra_buttons=POWEROUTLET_BUTTONS
buttons=('edit', 'delete'),
prepend_template=POWEROUTLET_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -551,10 +543,8 @@ class DeviceInterfaceTable(InterfaceTable):
linkify=True, linkify=True,
verbose_name='LAG' verbose_name='LAG'
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=Interface, extra_buttons=INTERFACE_BUTTONS
buttons=('edit', 'delete'),
prepend_template=INTERFACE_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -614,10 +604,8 @@ class DeviceFrontPortTable(FrontPortTable):
order_by=Accessor('_name'), order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=FrontPort, extra_buttons=FRONTPORT_BUTTONS
buttons=('edit', 'delete'),
prepend_template=FRONTPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -662,10 +650,8 @@ class DeviceRearPortTable(RearPortTable):
order_by=Accessor('_name'), order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=RearPort, extra_buttons=REARPORT_BUTTONS
buttons=('edit', 'delete'),
prepend_template=REARPORT_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -713,10 +699,8 @@ class DeviceDeviceBayTable(DeviceBayTable):
order_by=Accessor('_name'), order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=DeviceBay, extra_buttons=DEVICEBAY_BUTTONS
buttons=('edit', 'delete'),
prepend_template=DEVICEBAY_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -749,10 +733,8 @@ class ModuleBayTable(DeviceComponentTable):
class DeviceModuleBayTable(ModuleBayTable): class DeviceModuleBayTable(ModuleBayTable):
actions = ButtonsColumn( actions = ActionsColumn(
model=DeviceBay, extra_buttons=MODULEBAY_BUTTONS
buttons=('edit', 'delete'),
prepend_template=MODULEBAY_BUTTONS
) )
class Meta(DeviceComponentTable.Meta): class Meta(DeviceComponentTable.Meta):
@ -803,10 +785,7 @@ class DeviceInventoryItemTable(InventoryItemTable):
order_by=Accessor('_name'), order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
actions = ButtonsColumn( actions = ActionsColumn()
model=InventoryItem,
buttons=('edit', 'delete')
)
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):
model = InventoryItem model = InventoryItem

View File

@ -6,8 +6,7 @@ from dcim.models import (
InventoryItemTemplate, Manufacturer, ModuleBayTemplate, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate, InventoryItemTemplate, Manufacturer, ModuleBayTemplate, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate,
) )
from utilities.tables import ( from utilities.tables import (
ActionsColumn, BaseTable, BooleanColumn, ButtonsColumn, ColorColumn, LinkedCountColumn, MarkdownColumn, TagColumn, ActionsColumn, BaseTable, BooleanColumn, ColorColumn, LinkedCountColumn, MarkdownColumn, TagColumn, ToggleColumn,
ToggleColumn,
) )
from .template_code import MODULAR_COMPONENT_TEMPLATE_BUTTONS from .template_code import MODULAR_COMPONENT_TEMPLATE_BUTTONS
@ -113,10 +112,9 @@ class ComponentTemplateTable(BaseTable):
class ConsolePortTemplateTable(ComponentTemplateTable): class ConsolePortTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ActionsColumn(
model=ConsolePortTemplate, sequence=('edit', 'delete'),
buttons=('edit', 'delete'), extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -126,10 +124,9 @@ class ConsolePortTemplateTable(ComponentTemplateTable):
class ConsoleServerPortTemplateTable(ComponentTemplateTable): class ConsoleServerPortTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ActionsColumn(
model=ConsoleServerPortTemplate, sequence=('edit', 'delete'),
buttons=('edit', 'delete'), extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -139,10 +136,9 @@ class ConsoleServerPortTemplateTable(ComponentTemplateTable):
class PowerPortTemplateTable(ComponentTemplateTable): class PowerPortTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ActionsColumn(
model=PowerPortTemplate, sequence=('edit', 'delete'),
buttons=('edit', 'delete'), extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -152,10 +148,9 @@ class PowerPortTemplateTable(ComponentTemplateTable):
class PowerOutletTemplateTable(ComponentTemplateTable): class PowerOutletTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ActionsColumn(
model=PowerOutletTemplate, sequence=('edit', 'delete'),
buttons=('edit', 'delete'), extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -168,10 +163,9 @@ class InterfaceTemplateTable(ComponentTemplateTable):
mgmt_only = BooleanColumn( mgmt_only = BooleanColumn(
verbose_name='Management Only' verbose_name='Management Only'
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=InterfaceTemplate, sequence=('edit', 'delete'),
buttons=('edit', 'delete'), extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -185,10 +179,9 @@ class FrontPortTemplateTable(ComponentTemplateTable):
verbose_name='Position' verbose_name='Position'
) )
color = ColorColumn() color = ColorColumn()
actions = ButtonsColumn( actions = ActionsColumn(
model=FrontPortTemplate, sequence=('edit', 'delete'),
buttons=('edit', 'delete'), extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -199,10 +192,9 @@ class FrontPortTemplateTable(ComponentTemplateTable):
class RearPortTemplateTable(ComponentTemplateTable): class RearPortTemplateTable(ComponentTemplateTable):
color = ColorColumn() color = ColorColumn()
actions = ButtonsColumn( actions = ActionsColumn(
model=RearPortTemplate, sequence=('edit', 'delete'),
buttons=('edit', 'delete'), extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -212,9 +204,8 @@ class RearPortTemplateTable(ComponentTemplateTable):
class ModuleBayTemplateTable(ComponentTemplateTable): class ModuleBayTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ActionsColumn(
model=ModuleBayTemplate, sequence=('edit', 'delete')
buttons=('edit', 'delete')
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -224,9 +215,8 @@ class ModuleBayTemplateTable(ComponentTemplateTable):
class DeviceBayTemplateTable(ComponentTemplateTable): class DeviceBayTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ActionsColumn(
model=DeviceBayTemplate, sequence=('edit', 'delete')
buttons=('edit', 'delete')
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -236,9 +226,8 @@ class DeviceBayTemplateTable(ComponentTemplateTable):
class InventoryItemTemplateTable(ComponentTemplateTable): class InventoryItemTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ActionsColumn(
model=InventoryItemTemplate, sequence=('edit', 'delete')
buttons=('edit', 'delete')
) )
role = tables.Column( role = tables.Column(
linkify=True linkify=True

View File

@ -3,9 +3,9 @@ import django_tables2 as tables
from dcim.models import Location, Region, Site, SiteGroup from dcim.models import Location, Region, Site, SiteGroup
from tenancy.tables import TenantColumn from tenancy.tables import TenantColumn
from utilities.tables import ( from utilities.tables import (
BaseTable, ButtonsColumn, ChoiceFieldColumn, LinkedCountColumn, MarkdownColumn, MPTTColumn, TagColumn, ToggleColumn, ActionsColumn, BaseTable, ChoiceFieldColumn, LinkedCountColumn, MarkdownColumn, MPTTColumn, TagColumn, ToggleColumn,
) )
from .template_code import LOCATION_ELEVATIONS from .template_code import LOCATION_BUTTONS
__all__ = ( __all__ = (
'LocationTable', 'LocationTable',
@ -127,9 +127,8 @@ class LocationTable(BaseTable):
tags = TagColumn( tags = TagColumn(
url_name='dcim:location_list' url_name='dcim:location_list'
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=Location, extra_buttons=LOCATION_BUTTONS
prepend_template=LOCATION_ELEVATIONS
) )
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):

View File

@ -87,7 +87,7 @@ POWERFEED_CABLETERMINATION = """
<a href="{{ value.get_absolute_url }}">{{ value }}</a> <a href="{{ value.get_absolute_url }}">{{ value }}</a>
""" """
LOCATION_ELEVATIONS = """ LOCATION_BUTTONS = """
<a href="{% url 'dcim:rack_elevation_list' %}?site={{ record.site.slug }}&location_id={{ record.pk }}" class="btn btn-sm btn-primary" title="View elevations"> <a href="{% url 'dcim:rack_elevation_list' %}?site={{ record.site.slug }}&location_id={{ record.pk }}" class="btn btn-sm btn-primary" title="View elevations">
<i class="mdi mdi-server"></i> <i class="mdi mdi-server"></i>
</a> </a>
@ -99,8 +99,8 @@ LOCATION_ELEVATIONS = """
MODULAR_COMPONENT_TEMPLATE_BUTTONS = """ MODULAR_COMPONENT_TEMPLATE_BUTTONS = """
{% load helpers %} {% load helpers %}
{% if perms.dcim.add_invnetoryitemtemplate %} {% if perms.dcim.add_inventoryitemtemplate %}
<a href="{% url 'dcim:inventoryitemtemplate_add' %}?device_type={{ record.device_type.pk }}&component_type={{ record|content_type_id }}&component_id={{ record.pk }}&return_url={{ request.path }}" title="Add inventory item" class="btn btn-primary btn-sm"> <a href="{% url 'dcim:inventoryitemtemplate_add' %}?device_type={{ record.device_type_id }}&component_type={{ record|content_type_id }}&component_id={{ record.pk }}&return_url={{ request.path }}" title="Add inventory item" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> <i class="mdi mdi-plus-thick" aria-hidden="true"></i>
</a> </a>
{% endif %} {% endif %}

View File

@ -5,8 +5,8 @@ from django_tables2.utils import Accessor
from dcim.models import Interface from dcim.models import Interface
from tenancy.tables import TenantColumn from tenancy.tables import TenantColumn
from utilities.tables import ( from utilities.tables import (
ActionsColumn, BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ContentTypeColumn, LinkedCountColumn, ActionsColumn, BaseTable, BooleanColumn, ChoiceFieldColumn, ContentTypeColumn, LinkedCountColumn, TagColumn,
TagColumn, TemplateColumn, ToggleColumn, TemplateColumn, ToggleColumn,
) )
from virtualization.models import VMInterface from virtualization.models import VMInterface
from ipam.models import * from ipam.models import *
@ -38,7 +38,7 @@ VLAN_PREFIXES = """
{% endfor %} {% endfor %}
""" """
VLANGROUP_ADD_VLAN = """ VLANGROUP_BUTTONS = """
{% with next_vid=record.get_next_available_vid %} {% with next_vid=record.get_next_available_vid %}
{% if next_vid and perms.ipam.add_vlan %} {% if next_vid and perms.ipam.add_vlan %}
<a href="{% url 'ipam:vlan_add' %}?group={{ record.pk }}&vid={{ next_vid }}" title="Add VLAN" class="btn btn-sm btn-success"> <a href="{% url 'ipam:vlan_add' %}?group={{ record.pk }}&vid={{ next_vid }}" title="Add VLAN" class="btn btn-sm btn-success">
@ -77,9 +77,8 @@ class VLANGroupTable(BaseTable):
tags = TagColumn( tags = TagColumn(
url_name='ipam:vlangroup_list' url_name='ipam:vlangroup_list'
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=VLANGroup, extra_buttons=VLANGROUP_BUTTONS
prepend_template=VLANGROUP_ADD_VLAN
) )
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):

View File

@ -1,9 +1,10 @@
from collections import namedtuple
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional from typing import Optional
import django_tables2 as tables import django_tables2 as tables
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.template import Context, Template
from django.urls import reverse from django.urls import reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django_tables2.utils import Accessor from django_tables2.utils import Accessor
@ -14,7 +15,6 @@ from utilities.utils import content_type_identifier, content_type_name
__all__ = ( __all__ = (
'ActionsColumn', 'ActionsColumn',
'BooleanColumn', 'BooleanColumn',
'ButtonsColumn',
'ChoiceFieldColumn', 'ChoiceFieldColumn',
'ColorColumn', 'ColorColumn',
'ColoredLabelColumn', 'ColoredLabelColumn',
@ -100,7 +100,14 @@ class ActionsItem:
class ActionsColumn(tables.Column): class ActionsColumn(tables.Column):
attrs = {'td': {'class': 'text-end noprint'}} """
A dropdown menu which provides edit, delete, and changelog links for an object. Can optionally include
additional buttons rendered from a template string.
:param sequence: The ordered list of dropdown menu items to include
:param extra_buttons: A Django template string which renders additional buttons preceding the actions dropdown
"""
attrs = {'td': {'class': 'text-end text-nowrap noprint'}}
empty_values = () empty_values = ()
actions = { actions = {
'edit': ActionsItem('Edit', 'pencil', 'change'), 'edit': ActionsItem('Edit', 'pencil', 'change'),
@ -108,12 +115,10 @@ class ActionsColumn(tables.Column):
'changelog': ActionsItem('Changelog', 'history'), 'changelog': ActionsItem('Changelog', 'history'),
} }
def __init__(self, *args, extra_actions=None, sequence=('edit', 'delete', 'changelog'), **kwargs): def __init__(self, *args, sequence=('edit', 'delete', 'changelog'), extra_buttons='', **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
# Add/update any extra actions passed self.extra_buttons = extra_buttons
if extra_actions:
self.actions.update(extra_actions)
# Determine which actions to enable # Determine which actions to enable
self.actions = { self.actions = {
@ -134,9 +139,10 @@ class ActionsColumn(tables.Column):
url_appendix = f'?return_url={request.path}' if request else '' url_appendix = f'?return_url={request.path}' if request else ''
links = [] links = []
user = getattr(request, 'user', AnonymousUser())
for action, attrs in self.actions.items(): for action, attrs in self.actions.items():
permission = f'{model._meta.app_label}.{attrs.permission}_{model._meta.model_name}' permission = f'{model._meta.app_label}.{attrs.permission}_{model._meta.model_name}'
if attrs.permission is None or request.user.has_perm(permission): if attrs.permission is None or user.has_perm(permission):
url = reverse(f'{viewname_base}_{action}', kwargs={'pk': record.pk}) url = reverse(f'{viewname_base}_{action}', kwargs={'pk': record.pk})
links.append(f'<li><a class="dropdown-item" href="{url}{url_appendix}">' links.append(f'<li><a class="dropdown-item" href="{url}{url_appendix}">'
f'<i class="mdi mdi-{attrs.icon}"></i> {attrs.title}</a></li>') f'<i class="mdi mdi-{attrs.icon}"></i> {attrs.title}</a></li>')
@ -144,68 +150,21 @@ class ActionsColumn(tables.Column):
if not links: if not links:
return '' return ''
menu = f'<div class="dropdown">' \ menu = f'<span class="dropdown">' \
f'<a class="btn btn-sm btn-outline-secondary dropdown-toggle" href="#" type="button" data-bs-toggle="dropdown">' \ f'<a class="btn btn-sm btn-secondary dropdown-toggle" href="#" type="button" data-bs-toggle="dropdown">' \
f'<i class="mdi mdi-wrench"></i></a>' \ f'<i class="mdi mdi-wrench"></i></a>' \
f'<ul class="dropdown-menu">{"".join(links)}</ul></div>' f'<ul class="dropdown-menu">{"".join(links)}</ul></span>'
# Render any extra buttons from template code
if self.extra_buttons:
template = Template(self.extra_buttons)
context = getattr(table, "context", Context())
context.update({'record': record})
menu = template.render(context) + menu
return mark_safe(menu) return mark_safe(menu)
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)
"""
buttons = ('changelog', 'edit', 'delete')
attrs = {'td': {'class': 'text-end text-nowrap noprint'}}
# Note that braces are escaped to allow for string formatting prior to template rendering
template_code = """
{{% if "changelog" in buttons %}}
<a href="{{% url '{app_label}:{model_name}_changelog' pk=record.pk %}}" class="btn btn-outline-dark btn-sm" title="Change log">
<i class="mdi mdi-history"></i>
</a>
{{% endif %}}
{{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}}
<a href="{{% url '{app_label}:{model_name}_edit' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-sm btn-warning" title="Edit">
<i class="mdi mdi-pencil"></i>
</a>
{{% endif %}}
{{% if "delete" in buttons and perms.{app_label}.delete_{model_name} %}}
<a href="{{% url '{app_label}:{model_name}_delete' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-sm btn-danger" title="Delete">
<i class="mdi mdi-trash-can-outline"></i>
</a>
{{% endif %}}
"""
def __init__(self, model, *args, buttons=None, 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,
buttons=buttons
)
super().__init__(template_code=template_code, *args, **kwargs)
# Exclude from export by default
if 'exclude_from_export' not in kwargs:
self.exclude_from_export = True
self.extra_context.update({
'buttons': buttons or self.buttons,
})
def header(self):
return ''
class ChoiceFieldColumn(tables.Column): class ChoiceFieldColumn(tables.Column):
""" """
Render a ChoiceField value inside a <span> indicating a particular CSS class. This is useful for displaying colored Render a ChoiceField value inside a <span> indicating a particular CSS class. This is useful for displaying colored

View File

@ -30,7 +30,8 @@ class TagColumnTest(TestCase):
def test_tagcolumn(self): def test_tagcolumn(self):
template = Template('{% load render_table from django_tables2 %}{% render_table table %}') template = Template('{% load render_table from django_tables2 %}{% render_table table %}')
table = TagColumnTable(Site.objects.all(), orderable=False)
context = Context({ context = Context({
'table': TagColumnTable(Site.objects.all(), orderable=False) 'table': table
}) })
template.render(context) template.render(context)

View File

@ -3,7 +3,7 @@ import django_tables2 as tables
from dcim.tables.devices import BaseInterfaceTable from dcim.tables.devices import BaseInterfaceTable
from tenancy.tables import TenantColumn from tenancy.tables import TenantColumn
from utilities.tables import ( from utilities.tables import (
BaseTable, ButtonsColumn, ChoiceFieldColumn, ColoredLabelColumn, LinkedCountColumn, MarkdownColumn, TagColumn, ActionsColumn, BaseTable, ChoiceFieldColumn, ColoredLabelColumn, LinkedCountColumn, MarkdownColumn, TagColumn,
ToggleColumn, ToggleColumn,
) )
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
@ -183,10 +183,9 @@ class VirtualMachineVMInterfaceTable(VMInterfaceTable):
bridge = tables.Column( bridge = tables.Column(
linkify=True linkify=True
) )
actions = ButtonsColumn( actions = ActionsColumn(
model=VMInterface, sequence=('edit', 'delete'),
buttons=('edit', 'delete'), extra_buttons=VMINTERFACE_BUTTONS
prepend_template=VMINTERFACE_BUTTONS
) )
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):