Due to all the meta magic going on, I am currently using:
class StatsTable(tables.Table):
class Meta:
orderable = False
attrs = {'class': 'tablesorter'}
def __init__(self, form, request, *args, **kwargs):
rf_values = form.get_values()
rf_annotations = form.get_annotations()
rf_filter = form.get_filter()
rf_calculations = form.get_calculations()
data = list(
HourlyStat.objects.filter(**rf_filter).values(*rf_values).annotate(**rf_annotations).order_by('-clicks')
)
super(StatsTable, self).__init__(data, *args, **kwargs)
columns = rf_values + rf_annotations.keys() + rf_calculations
for col in columns:
self.base_columns[col] = tables.Column()
really the only issue with me using it like this is the fact that I can't simply call super() last it has to be in the middle. I guess its because the meta class doesn't actually look for base_columns on itself but only on inherited models. Really this just seems way messier than the self.fields on django forms.
This is odd
I add dynamic columns by just appending them to self.base_columns:
self.base_columns['column_name'] = tables.Column()
One thing I found annoying is that by doing that, I modify the class attribute, not the instance attribute, so any column I add on a request, will be shown on every subsequent request to the table, the solution to real dynamic columns I found was:
class ComponenteContableColumns(tables.Table):
"""Table that shows ComponentesContables as columns."""
a_static_columns = tables.Column()
def __init__(self, *args, **kwargs):
# Create a copy of base_columns to restore at the end.
self._bc = copy.deepcopy(self.base_columns)
# Your dynamic columns added here:
if today is 'monday':
self.base_columns['monday'] = tables.Column()
if today is 'tuesday':
self.base_columns['tuesday'] = tables.Column()
super().__init__(*args, **kwargs)
# restore original base_column to avoid permanent columns.
type(self).base_columns = self._bc
I have the same issue as @jmfederico and have had to put his suggested hack (workaround) in place. Is there a better suggestion on how to dynamically add columns to a table? I have a table with dates from a query along the top so depending on how it is filtered it may have more or less and different dates. I couldn't work out for the life of me why sometimes we had some extra columns that weren't in the query and figured out it was this same problem.
For reference here is my table class
class ActivitySummaryTable(TableWithRawData):
activity = tables.Column(verbose_name=_('Activity'), orderable=False)
# the rest of the columns will be added based on the filter provided
def __init__(self, extra_cols, *args, **kwargs):
"""Pass in a list of tuples of extra columns to add in the format (colunm_name, column)"""
# Temporary hack taken from: https://github.com/bradleyayers/django-tables2/issues/70 to avoid the issue where
# we got the same columns from the previous instance added back
# Create a copy of base_columns to restore at the end.
_bc = copy.deepcopy(self.base_columns)
for col_name, col in extra_cols:
self.base_columns[col_name] = col
super(ActivitySummaryTable, self).__init__(*args, **kwargs)
# restore original base_column to avoid permanent columns.
type(self).base_columns = _bc
class Meta:
attrs = {'class': 'table'}
order_by = ('activity',)
Example where we filter the dates and then there are 2 stray dates added at the end
fixed in 817d711 using the extra_columns
argument
Most helpful comment
This is odd
I add dynamic columns by just appending them to self.base_columns:
One thing I found annoying is that by doing that, I modify the class attribute, not the instance attribute, so any column I add on a request, will be shown on every subsequent request to the table, the solution to real dynamic columns I found was: