mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixes #9313: Remove HTML code from CSV output of many-to-many relationships
This commit is contained in:
@ -16,6 +16,7 @@
|
|||||||
* [#9267](https://github.com/netbox-community/netbox/issues/9267) - Remove invalid entry in IP address role choices
|
* [#9267](https://github.com/netbox-community/netbox/issues/9267) - Remove invalid entry in IP address role choices
|
||||||
* [#9306](https://github.com/netbox-community/netbox/issues/9306) - Include VC master interfaces when selecting a LAG/bridge for a VC member interface
|
* [#9306](https://github.com/netbox-community/netbox/issues/9306) - Include VC master interfaces when selecting a LAG/bridge for a VC member interface
|
||||||
* [#9311](https://github.com/netbox-community/netbox/issues/9311) - Permit creating contact assignment without a priority via the REST API
|
* [#9311](https://github.com/netbox-community/netbox/issues/9311) - Permit creating contact assignment without a priority via the REST API
|
||||||
|
* [#9313](https://github.com/netbox-community/netbox/issues/9313) - Remove HTML code from CSV output of many-to-many relationships
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class CircuitTable(NetBoxTable):
|
|||||||
)
|
)
|
||||||
commit_rate = CommitRateColumn()
|
commit_rate = CommitRateColumn()
|
||||||
comments = columns.MarkdownColumn()
|
comments = columns.MarkdownColumn()
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -14,7 +14,7 @@ class ProviderTable(NetBoxTable):
|
|||||||
name = tables.Column(
|
name = tables.Column(
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
asns = tables.ManyToManyColumn(
|
asns = columns.ManyToManyColumn(
|
||||||
linkify_item=True,
|
linkify_item=True,
|
||||||
verbose_name='ASNs'
|
verbose_name='ASNs'
|
||||||
)
|
)
|
||||||
@ -31,7 +31,7 @@ class ProviderTable(NetBoxTable):
|
|||||||
verbose_name='Circuits'
|
verbose_name='Circuits'
|
||||||
)
|
)
|
||||||
comments = columns.MarkdownColumn()
|
comments = columns.MarkdownColumn()
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -190,7 +190,7 @@ class DeviceTable(NetBoxTable):
|
|||||||
verbose_name='VC Priority'
|
verbose_name='VC Priority'
|
||||||
)
|
)
|
||||||
comments = columns.MarkdownColumn()
|
comments = columns.MarkdownColumn()
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -43,7 +43,7 @@ class ManufacturerTable(NetBoxTable):
|
|||||||
verbose_name='Platforms'
|
verbose_name='Platforms'
|
||||||
)
|
)
|
||||||
slug = tables.Column()
|
slug = tables.Column()
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -26,7 +26,7 @@ class PowerPanelTable(NetBoxTable):
|
|||||||
url_params={'power_panel_id': 'pk'},
|
url_params={'power_panel_id': 'pk'},
|
||||||
verbose_name='Feeds'
|
verbose_name='Feeds'
|
||||||
)
|
)
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -69,7 +69,7 @@ class RackTable(NetBoxTable):
|
|||||||
orderable=False,
|
orderable=False,
|
||||||
verbose_name='Power'
|
verbose_name='Power'
|
||||||
)
|
)
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -26,7 +26,7 @@ class RegionTable(NetBoxTable):
|
|||||||
url_params={'region_id': 'pk'},
|
url_params={'region_id': 'pk'},
|
||||||
verbose_name='Sites'
|
verbose_name='Sites'
|
||||||
)
|
)
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
@ -55,7 +55,7 @@ class SiteGroupTable(NetBoxTable):
|
|||||||
url_params={'group_id': 'pk'},
|
url_params={'group_id': 'pk'},
|
||||||
verbose_name='Sites'
|
verbose_name='Sites'
|
||||||
)
|
)
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
@ -86,7 +86,7 @@ class SiteTable(NetBoxTable):
|
|||||||
group = tables.Column(
|
group = tables.Column(
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
asns = tables.ManyToManyColumn(
|
asns = columns.ManyToManyColumn(
|
||||||
linkify_item=True,
|
linkify_item=True,
|
||||||
verbose_name='ASNs'
|
verbose_name='ASNs'
|
||||||
)
|
)
|
||||||
@ -98,7 +98,7 @@ class SiteTable(NetBoxTable):
|
|||||||
)
|
)
|
||||||
tenant = TenantColumn()
|
tenant = TenantColumn()
|
||||||
comments = columns.MarkdownColumn()
|
comments = columns.MarkdownColumn()
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
@ -137,7 +137,7 @@ class LocationTable(NetBoxTable):
|
|||||||
url_params={'location_id': 'pk'},
|
url_params={'location_id': 'pk'},
|
||||||
verbose_name='Devices'
|
verbose_name='Devices'
|
||||||
)
|
)
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -118,7 +118,7 @@ class ASNTable(NetBoxTable):
|
|||||||
url_params={'asn_id': 'pk'},
|
url_params={'asn_id': 'pk'},
|
||||||
verbose_name='Provider Count'
|
verbose_name='Provider Count'
|
||||||
)
|
)
|
||||||
sites = tables.ManyToManyColumn(
|
sites = columns.ManyToManyColumn(
|
||||||
linkify_item=True,
|
linkify_item=True,
|
||||||
verbose_name='Sites'
|
verbose_name='Sites'
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,7 @@ from django.conf import settings
|
|||||||
from django.contrib.auth.models import AnonymousUser
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from django.db.models import DateField, DateTimeField
|
from django.db.models import DateField, DateTimeField
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.urls import NoReverseMatch, reverse
|
from django.urls import reverse
|
||||||
from django.utils.formats import date_format
|
from django.utils.formats import date_format
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django_tables2.columns import library
|
from django_tables2.columns import library
|
||||||
@ -27,6 +27,7 @@ __all__ = (
|
|||||||
'CustomLinkColumn',
|
'CustomLinkColumn',
|
||||||
'LinkedCountColumn',
|
'LinkedCountColumn',
|
||||||
'MarkdownColumn',
|
'MarkdownColumn',
|
||||||
|
'ManyToManyColumn',
|
||||||
'MPTTColumn',
|
'MPTTColumn',
|
||||||
'TagColumn',
|
'TagColumn',
|
||||||
'TemplateColumn',
|
'TemplateColumn',
|
||||||
@ -35,6 +36,10 @@ __all__ = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Django-tables2 overrides
|
||||||
|
#
|
||||||
|
|
||||||
@library.register
|
@library.register
|
||||||
class DateColumn(tables.DateColumn):
|
class DateColumn(tables.DateColumn):
|
||||||
"""
|
"""
|
||||||
@ -42,7 +47,6 @@ class DateColumn(tables.DateColumn):
|
|||||||
tables and null when exporting data. It is registered in the tables library to use this class instead of the
|
tables and null when exporting data. It is registered in the tables library to use this class instead of the
|
||||||
default, making this behavior consistent in all fields of type DateField.
|
default, making this behavior consistent in all fields of type DateField.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def value(self, value):
|
def value(self, value):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@ -59,7 +63,6 @@ class DateTimeColumn(tables.DateTimeColumn):
|
|||||||
tables and null when exporting data. It is registered in the tables library to use this class instead of the
|
tables and null when exporting data. It is registered in the tables library to use this class instead of the
|
||||||
default, making this behavior consistent in all fields of type DateTimeField.
|
default, making this behavior consistent in all fields of type DateTimeField.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def value(self, value):
|
def value(self, value):
|
||||||
if value:
|
if value:
|
||||||
return date_format(value, format="SHORT_DATETIME_FORMAT")
|
return date_format(value, format="SHORT_DATETIME_FORMAT")
|
||||||
@ -71,6 +74,39 @@ class DateTimeColumn(tables.DateTimeColumn):
|
|||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ManyToManyColumn(tables.ManyToManyColumn):
|
||||||
|
"""
|
||||||
|
Overrides django-tables2's stock ManyToManyColumn to ensure that value() returns only plaintext data.
|
||||||
|
"""
|
||||||
|
def value(self, value):
|
||||||
|
items = [self.transform(item) for item in self.filter(value)]
|
||||||
|
return self.separator.join(items)
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateColumn(tables.TemplateColumn):
|
||||||
|
"""
|
||||||
|
Overrides django-tables2's stock TemplateColumn class to render a placeholder symbol 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
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Custom columns
|
||||||
|
#
|
||||||
|
|
||||||
class ToggleColumn(tables.CheckBoxColumn):
|
class ToggleColumn(tables.CheckBoxColumn):
|
||||||
"""
|
"""
|
||||||
Extend CheckBoxColumn to add a "toggle all" checkbox in the column header.
|
Extend CheckBoxColumn to add a "toggle all" checkbox in the column header.
|
||||||
@ -112,26 +148,6 @@ class BooleanColumn(tables.Column):
|
|||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
class TemplateColumn(tables.TemplateColumn):
|
|
||||||
"""
|
|
||||||
Overrides django-tables2's stock TemplateColumn class to render a placeholder symbol 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
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ActionsItem:
|
class ActionsItem:
|
||||||
title: str
|
title: str
|
||||||
|
@ -38,7 +38,7 @@ class TenantTable(NetBoxTable):
|
|||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
comments = columns.MarkdownColumn()
|
comments = columns.MarkdownColumn()
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -40,7 +40,7 @@ class ClusterGroupTable(NetBoxTable):
|
|||||||
url_params={'group_id': 'pk'},
|
url_params={'group_id': 'pk'},
|
||||||
verbose_name='Clusters'
|
verbose_name='Clusters'
|
||||||
)
|
)
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
@ -83,7 +83,7 @@ class ClusterTable(NetBoxTable):
|
|||||||
verbose_name='VMs'
|
verbose_name='VMs'
|
||||||
)
|
)
|
||||||
comments = columns.MarkdownColumn()
|
comments = columns.MarkdownColumn()
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -78,7 +78,7 @@ class VMInterfaceTable(BaseInterfaceTable):
|
|||||||
vrf = tables.Column(
|
vrf = tables.Column(
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
contacts = tables.ManyToManyColumn(
|
contacts = columns.ManyToManyColumn(
|
||||||
linkify_item=True
|
linkify_item=True
|
||||||
)
|
)
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
Reference in New Issue
Block a user