mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
Fixes #6895: Remove errant markup for null values in CSV export
This commit is contained in:
parent
14b065cf5f
commit
1f1a05dc67
@ -4,6 +4,7 @@
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [#6895](https://github.com/netbox-community/netbox/issues/6895) - Remove errant markup for null values in CSV export
|
||||
* [#7373](https://github.com/netbox-community/netbox/issues/7373) - Fix flashing when server, client, and browser color-mode preferences are mismatched
|
||||
|
||||
---
|
||||
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
from django_tables2.utils import Accessor
|
||||
|
||||
from dcim.models import Cable
|
||||
from utilities.tables import BaseTable, ChoiceFieldColumn, ColorColumn, TagColumn, ToggleColumn
|
||||
from utilities.tables import BaseTable, ChoiceFieldColumn, ColorColumn, TagColumn, TemplateColumn, ToggleColumn
|
||||
from .template_code import CABLE_LENGTH, CABLE_TERMINATION_PARENT
|
||||
|
||||
__all__ = (
|
||||
@ -45,7 +45,7 @@ class CableTable(BaseTable):
|
||||
verbose_name='Termination B'
|
||||
)
|
||||
status = ChoiceFieldColumn()
|
||||
length = tables.TemplateColumn(
|
||||
length = TemplateColumn(
|
||||
template_code=CABLE_LENGTH,
|
||||
order_by='_abs_length'
|
||||
)
|
||||
|
@ -9,7 +9,7 @@ from dcim.models import (
|
||||
from tenancy.tables import TenantColumn
|
||||
from utilities.tables import (
|
||||
BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn,
|
||||
MarkdownColumn, TagColumn, ToggleColumn,
|
||||
MarkdownColumn, TagColumn, TemplateColumn, ToggleColumn,
|
||||
)
|
||||
from .template_code import (
|
||||
CABLETERMINATION, CONSOLEPORT_BUTTONS, CONSOLESERVERPORT_BUTTONS, DEVICE_LINK, DEVICEBAY_BUTTONS, DEVICEBAY_STATUS,
|
||||
@ -258,7 +258,7 @@ class CableTerminationTable(BaseTable):
|
||||
orderable=False,
|
||||
verbose_name='Cable Color'
|
||||
)
|
||||
cable_peer = tables.TemplateColumn(
|
||||
cable_peer = TemplateColumn(
|
||||
accessor='_cable_peer',
|
||||
template_code=CABLETERMINATION,
|
||||
orderable=False,
|
||||
@ -268,7 +268,7 @@ class CableTerminationTable(BaseTable):
|
||||
|
||||
|
||||
class PathEndpointTable(CableTerminationTable):
|
||||
connection = tables.TemplateColumn(
|
||||
connection = TemplateColumn(
|
||||
accessor='_path.last_node',
|
||||
template_code=CABLETERMINATION,
|
||||
verbose_name='Connection',
|
||||
@ -470,7 +470,7 @@ class BaseInterfaceTable(BaseTable):
|
||||
verbose_name='IP Addresses'
|
||||
)
|
||||
untagged_vlan = tables.Column(linkify=True)
|
||||
tagged_vlans = tables.TemplateColumn(
|
||||
tagged_vlans = TemplateColumn(
|
||||
template_code=INTERFACE_TAGGED_VLANS,
|
||||
orderable=False,
|
||||
verbose_name='Tagged VLANs'
|
||||
|
@ -5,13 +5,11 @@ CABLETERMINATION = """
|
||||
<i class="mdi mdi-chevron-right"></i>
|
||||
{% endif %}
|
||||
<a href="{{ value.get_absolute_url }}">{{ value }}</a>
|
||||
{% else %}
|
||||
—
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
CABLE_LENGTH = """
|
||||
{% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}—{% endif %}
|
||||
{% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% endif %}
|
||||
"""
|
||||
|
||||
CABLE_TERMINATION_PARENT = """
|
||||
@ -63,8 +61,6 @@ INTERFACE_TAGGED_VLANS = """
|
||||
{% endfor %}
|
||||
{% elif record.mode == 'tagged-all' %}
|
||||
All
|
||||
{% else %}
|
||||
—
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
|
@ -39,15 +39,7 @@ PREFIXFLAT_LINK = """
|
||||
{% if record.pk %}
|
||||
<a href="{% url 'ipam:prefix' pk=record.pk %}">{{ record.prefix }}</a>
|
||||
{% else %}
|
||||
—
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
PREFIX_ROLE_LINK = """
|
||||
{% if record.role %}
|
||||
<a href="{% url 'ipam:prefix_list' %}?role={{ record.role.slug }}">{{ record.role }}</a>
|
||||
{% else %}
|
||||
—
|
||||
{{ record.prefix }}
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
@ -218,8 +210,8 @@ class PrefixTable(BaseTable):
|
||||
linkify=True,
|
||||
verbose_name='VLAN'
|
||||
)
|
||||
role = tables.TemplateColumn(
|
||||
template_code=PREFIX_ROLE_LINK
|
||||
role = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
is_pool = BooleanColumn(
|
||||
verbose_name='Pool'
|
||||
@ -264,8 +256,8 @@ class IPRangeTable(BaseTable):
|
||||
status = ChoiceFieldColumn(
|
||||
default=AVAILABLE_LABEL
|
||||
)
|
||||
role = tables.TemplateColumn(
|
||||
template_code=PREFIX_ROLE_LINK
|
||||
role = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
|
||||
|
@ -6,7 +6,7 @@ from dcim.models import Interface
|
||||
from tenancy.tables import TenantColumn
|
||||
from utilities.tables import (
|
||||
BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ContentTypeColumn, LinkedCountColumn, TagColumn,
|
||||
ToggleColumn,
|
||||
TemplateColumn, ToggleColumn,
|
||||
)
|
||||
from virtualization.models import VMInterface
|
||||
from ipam.models import *
|
||||
@ -35,19 +35,9 @@ VLAN_LINK = """
|
||||
VLAN_PREFIXES = """
|
||||
{% for prefix in record.prefixes.all %}
|
||||
<a href="{% url 'ipam:prefix' pk=prefix.pk %}">{{ prefix }}</a>{% if not forloop.last %}<br />{% endif %}
|
||||
{% empty %}
|
||||
—
|
||||
{% endfor %}
|
||||
"""
|
||||
|
||||
VLAN_ROLE_LINK = """
|
||||
{% if record.role %}
|
||||
<a href="{% url 'ipam:vlan_list' %}?role={{ record.role.slug }}">{{ record.role }}</a>
|
||||
{% else %}
|
||||
—
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
VLANGROUP_ADD_VLAN = """
|
||||
{% with next_vid=record.get_next_available_vid %}
|
||||
{% if next_vid and perms.ipam.add_vlan %}
|
||||
@ -115,10 +105,10 @@ class VLANTable(BaseTable):
|
||||
status = ChoiceFieldColumn(
|
||||
default=AVAILABLE_LABEL
|
||||
)
|
||||
role = tables.TemplateColumn(
|
||||
template_code=VLAN_ROLE_LINK
|
||||
role = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
prefixes = tables.TemplateColumn(
|
||||
prefixes = TemplateColumn(
|
||||
template_code=VLAN_PREFIXES,
|
||||
orderable=False,
|
||||
verbose_name='Prefixes'
|
||||
@ -190,8 +180,8 @@ class InterfaceVLANTable(BaseTable):
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
status = ChoiceFieldColumn()
|
||||
role = tables.TemplateColumn(
|
||||
template_code=VLAN_ROLE_LINK
|
||||
role = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
|
@ -1,7 +1,7 @@
|
||||
import django_tables2 as tables
|
||||
|
||||
from tenancy.tables import TenantColumn
|
||||
from utilities.tables import BaseTable, BooleanColumn, TagColumn, ToggleColumn
|
||||
from utilities.tables import BaseTable, BooleanColumn, TagColumn, TemplateColumn, ToggleColumn
|
||||
from ipam.models import *
|
||||
|
||||
__all__ = (
|
||||
@ -11,9 +11,7 @@ __all__ = (
|
||||
|
||||
VRF_TARGETS = """
|
||||
{% for rt in value.all %}
|
||||
<a href="{{ rt.get_absolute_url }}">{{ rt }}</a>{% if not forloop.last %}<br />{% endif %}
|
||||
{% empty %}
|
||||
—
|
||||
<a href="{{ rt.get_absolute_url }}">{{ rt }}</a>{% if not forloop.last %}<br />{% endif %}
|
||||
{% endfor %}
|
||||
"""
|
||||
|
||||
@ -34,11 +32,11 @@ class VRFTable(BaseTable):
|
||||
enforce_unique = BooleanColumn(
|
||||
verbose_name='Unique'
|
||||
)
|
||||
import_targets = tables.TemplateColumn(
|
||||
import_targets = TemplateColumn(
|
||||
template_code=VRF_TARGETS,
|
||||
orderable=False
|
||||
)
|
||||
export_targets = tables.TemplateColumn(
|
||||
export_targets = TemplateColumn(
|
||||
template_code=VRF_TARGETS,
|
||||
orderable=False
|
||||
)
|
||||
|
@ -157,6 +157,25 @@ class BooleanColumn(tables.Column):
|
||||
return str(value)
|
||||
|
||||
|
||||
class TemplateColumn(tables.TemplateColumn):
|
||||
"""
|
||||
Overrides the stock TemplateColumn to render a placeholder if the returned value is an empty string.
|
||||
"""
|
||||
PLACEHOLDER = mark_safe('—')
|
||||
|
||||
def render(self, *args, **kwargs):
|
||||
ret = super().render(*args, **kwargs)
|
||||
if not ret.strip():
|
||||
return self.PLACEHOLDER
|
||||
return ret
|
||||
|
||||
def value(self, **kwargs):
|
||||
ret = super().value(**kwargs)
|
||||
if ret == self.PLACEHOLDER:
|
||||
return ''
|
||||
return ret
|
||||
|
||||
|
||||
class ButtonsColumn(tables.TemplateColumn):
|
||||
"""
|
||||
Render edit, delete, and changelog buttons for an object.
|
||||
|
Loading…
Reference in New Issue
Block a user