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

Add support for custom fields in tables (#5460)

* Add support for custom fields in tables

* Fix empty list displays as none

Co-authored-by: TomGrozev <TomGrozev@users.noreply.github.com>
Co-authored-by: Jeremy Stretch <jeremy@netverity.dev>
This commit is contained in:
Tom Grozev
2021-03-29 21:15:21 +00:00
committed by GitHub
parent c7040fd418
commit be3d33eebd

View File

@ -1,7 +1,9 @@
import django_tables2 as tables
from django.contrib.auth.models import AnonymousUser
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import FieldDoesNotExist
from django.db.models import Func, F, Value
from django.db.models.fields.related import RelatedField
from django.urls import reverse
from django.utils.html import strip_tags
@ -9,6 +11,7 @@ from django.utils.safestring import mark_safe
from django_tables2 import RequestConfig
from django_tables2.data import TableQuerysetData
from .models import CustomField
from .paginator import EnhancedPaginator, get_paginate_count
@ -30,12 +33,25 @@ class BaseTable(tables.Table):
:param user: Personalize table display for the given user (optional). Has no effect if AnonymousUser is passed.
"""
class Meta:
attrs = {
'class': 'table table-hover table-headings',
}
def __init__(self, *args, user=None, **kwargs):
# Add custom field columns
obj_type = ContentType.objects.get_for_model(self._meta.model)
custom_fields = {}
for cf in CustomField.objects.filter(content_types=obj_type):
name = 'cf_{}'.format(cf.name)
label = cf.label if cf.label != '' else cf.name
self.base_columns[name] = CustomFieldColumn(verbose_name=label)
custom_fields[name] = cf
self._meta.fields += tuple(custom_fields.keys())
# Init table
super().__init__(*args, **kwargs)
# Set default empty_text if none was provided
@ -73,6 +89,12 @@ class BaseTable(tables.Table):
# Dynamically update the table's QuerySet to ensure related fields are pre-fetched
if isinstance(self.data, TableQuerysetData):
# Extract custom field values
cf_fields = {}
for key, cf in custom_fields.items():
cf_fields[key] = Func(F('custom_field_data'), Value(cf.name), function='jsonb_extract_path_text')
self.data.data = self.data.data.annotate(**cf_fields)
prefetch_fields = []
for column in self.columns:
if column.visible:
@ -316,6 +338,28 @@ class TagColumn(tables.TemplateColumn):
return ",".join([tag.name for tag in value.all()])
class CustomFieldColumn(tables.Column):
"""
Display custom fields in the appropriate format.
"""
def render(self, record, bound_column, value):
if isinstance(value, list):
if len(value):
template = ''
for v in value:
template += f'<span class="label label-default">{v}</span> '
else:
template = '<span class="text-muted">&mdash;</span>'
elif value:
template = value
else:
return self.default
return mark_safe(template)
def value(self, value):
return value
class MPTTColumn(tables.TemplateColumn):
"""
Display a nested hierarchy for MPTT-enabled models.
@ -362,3 +406,4 @@ def paginate_table(table, request):
'per_page': get_paginate_count(request)
}
RequestConfig(request, paginate).configure(table)