Copies column instances to be unique per table instance.
Fixes bug 964345. Incidentally fixes bug 964351 as well by wrapping the dropdown actions template code in a spaceless tag. Change-Id: I672cb517d230db235c90a403e9b8ac0740e8732d
This commit is contained in:
parent
28defb5ca9
commit
52b9e1982b
@ -617,13 +617,14 @@ class DataTableMetaclass(type):
|
||||
|
||||
# Gather columns; this prevents the column from being an attribute
|
||||
# on the DataTable class and avoids naming conflicts.
|
||||
columns = [(column_name, attrs.pop(column_name)) for
|
||||
column_name, obj in attrs.items()
|
||||
if issubclass(type(obj), (opts.column_class, Column))]
|
||||
# add a name attribute to each column
|
||||
for column_name, column in columns:
|
||||
column.name = column_name
|
||||
columns = []
|
||||
for name, obj in attrs.items():
|
||||
if issubclass(type(obj), (opts.column_class, Column)):
|
||||
column_instance = attrs.pop(name)
|
||||
column_instance.name = name
|
||||
columns.append((name, column_instance))
|
||||
columns.sort(key=lambda x: x[1].creation_counter)
|
||||
|
||||
# Iterate in reverse to preserve final order
|
||||
for base in bases[::-1]:
|
||||
if hasattr(base, 'base_columns'):
|
||||
@ -651,7 +652,8 @@ class DataTableMetaclass(type):
|
||||
actions_column.classes.append('actions_column')
|
||||
actions_column.auto = "actions"
|
||||
columns.append(("actions", actions_column))
|
||||
attrs['columns'] = SortedDict(columns)
|
||||
# Store this set of columns internally so we can copy them per-instance
|
||||
attrs['_columns'] = SortedDict(columns)
|
||||
|
||||
# Gather and register actions for later access since we only want
|
||||
# to instantiate them once.
|
||||
@ -698,11 +700,16 @@ class DataTable(object):
|
||||
def __init__(self, request, data=None, **kwargs):
|
||||
self._meta.request = request
|
||||
self._meta.data = data
|
||||
self._populate_data_cache()
|
||||
self.kwargs = kwargs
|
||||
|
||||
for column in self.columns.values():
|
||||
# Create a new set
|
||||
columns = []
|
||||
for key, _column in self._columns.items():
|
||||
column = copy.copy(_column)
|
||||
column.table = self
|
||||
columns.append((key, column))
|
||||
self.columns = SortedDict(columns)
|
||||
self._populate_data_cache()
|
||||
|
||||
# Associate these actions with this table
|
||||
for action in self.base_actions.values():
|
||||
|
@ -39,7 +39,7 @@ class MultiTableMixin(object):
|
||||
|
||||
def get_tables(self):
|
||||
if not self.table_classes:
|
||||
raise AttributeError('You must specify a one or more DataTable '
|
||||
raise AttributeError('You must specify one or more DataTable '
|
||||
'classes for the "table_classes" attribute '
|
||||
'on %s.' % self.__class__.__name__)
|
||||
if not self._tables:
|
||||
|
@ -1,5 +1,6 @@
|
||||
{% load horizon %}
|
||||
|
||||
{% spaceless %} {# This makes sure whitespace doesn't affect positioning for dropdown. #}
|
||||
{% if row_actions|length > 1 %}
|
||||
<div class="btn-group">
|
||||
{% for action in row_actions %}
|
||||
@ -25,3 +26,4 @@
|
||||
{% include "horizon/common/_data_table_row_action.html" %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endspaceless %}
|
||||
|
@ -308,9 +308,9 @@ class DataTableTests(test.TestCase):
|
||||
self.table = MyTable(self.request, TEST_DATA)
|
||||
row = self.table.get_rows()[0]
|
||||
row3 = self.table.get_rows()[2]
|
||||
id_col = self.table.base_columns['id']
|
||||
name_col = self.table.base_columns['name']
|
||||
value_col = self.table.base_columns['value']
|
||||
id_col = self.table.columns['id']
|
||||
name_col = self.table.columns['name']
|
||||
value_col = self.table.columns['value']
|
||||
# transform
|
||||
self.assertEqual(row.cells['id'].data, '1') # Standard attr access
|
||||
self.assertEqual(row.cells['name'].data, 'custom object_1') # Callable
|
||||
@ -552,3 +552,18 @@ class DataTableTests(test.TestCase):
|
||||
row_actions = self.table.get_row_actions(TEST_DATA[0])
|
||||
self.assertEqual(unicode(row_actions[0].verbose_name), "Delete Me")
|
||||
self.assertEqual(unicode(row_actions[1].verbose_name), "Log In")
|
||||
|
||||
def test_column_uniqueness(self):
|
||||
table1 = MyTable(self.request)
|
||||
table2 = MyTable(self.request)
|
||||
# Regression test for launchpad bug 964345.
|
||||
self.assertNotEqual(id(table1), id(table2))
|
||||
self.assertNotEqual(id(table1.columns), id(table2.columns))
|
||||
t1cols = table1.columns.values()
|
||||
t2cols = table2.columns.values()
|
||||
self.assertEqual(t1cols[0].name, t2cols[0].name)
|
||||
self.assertNotEqual(id(t1cols[0]), id(t2cols[0]))
|
||||
self.assertNotEqual(id(t1cols[0].table),
|
||||
id(t2cols[0].table))
|
||||
self.assertNotEqual(id(t1cols[0].table._data_cache),
|
||||
id(t2cols[0].table._data_cache))
|
||||
|
Loading…
x
Reference in New Issue
Block a user