diff --git a/iommi/table.py b/iommi/table.py index 805e8ff5..eab7acbd 100644 --- a/iommi/table.py +++ b/iommi/table.py @@ -1937,6 +1937,7 @@ def on_refine_done(self): self.initial_rows = self.rows self.header = HeaderConfig(_name='header', **self.header).refine_done(parent=self) self.row = RowConfig(**self.row).refine_done(parent=self) + self._preprocessed_rows = None # In bind initial_rows will be used to set these 3 (in that order) self.sorted_rows = None @@ -2220,7 +2221,8 @@ def on_bind(self) -> None: bind_member(self, name='bulk_container') def get_visible_rows(self): - self.visible_rows = self.parts.page.rows + if self.visible_rows is None: + self.visible_rows = self.parts.page.rows return self.visible_rows def _bind_query(self): @@ -2280,7 +2282,6 @@ def render_actions(self): def _prepare_auto_rowspan(self): auto_rowspan_columns = [column for column in values(self.columns) if column.auto_rowspan] if auto_rowspan_columns: - self.visible_rows = list(self.get_visible_rows()) no_value_set = object() for column in auto_rowspan_columns: if column.cell.attrs.get('rowspan', no_value_set) is not no_value_set: @@ -2412,12 +2413,13 @@ def cells_for_rows(self, paginate=True): rows = self.get_visible_rows() else: rows = self.sorted_and_filtered_rows - preprocessed_rows = self.invoke_callback(self.preprocess_rows, rows=rows) + if not self._preprocessed_rows: + self._preprocessed_rows = list(self.invoke_callback(self.preprocess_rows, rows=rows)) row_groups = [c for c in values(self.columns) if c.row_group.include] row_group_values = {c._name: None for c in row_groups} - for i, row in enumerate(preprocessed_rows): + for i, row in enumerate(self._preprocessed_rows): row = self.invoke_callback(self.preprocess_row, row=row) assert row is not None, 'preprocess_row must return the row' diff --git a/iommi/table__tests.py b/iommi/table__tests.py index 6df59661..19d5758c 100755 --- a/iommi/table__tests.py +++ b/iommi/table__tests.py @@ -4468,3 +4468,34 @@ def test_annotate_on_broken_filters(): """, ) + + +def test_auto_rowspan_and_render_twice_generator(NoSortTable): # noqa: N803 + class TestTable(NoSortTable): + foo = Column(auto_rowspan=True) + + rows = [ + Struct(foo=1), + Struct(foo=1), + Struct(foo=2), + Struct(foo=2), + ] + + # language=html + expected_html = """ + + + + + + + + + + +
Foo
1
1
2
2
""" + + t = TestTable(rows=(x for x in rows)) + t = t.bind(request=req('get')) + verify_table_html(table=t, expected_html=expected_html) + verify_table_html(table=t, expected_html=expected_html)