From 465d19169afc9fef09dbeff8c10d29d1c14b7b8e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michael=20Elsd=C3=B6rfer?= Date: Thu, 19 Jun 2008 18:52:07 +0000 Subject: [PATCH] fixed minor bug (caches not reset); added update() method --- django_tables/models.py | 5 +++++ django_tables/tables.py | 20 ++++++++++++++++++++ tests/test_basic.py | 27 ++++++++++++++++++++++----- tests/test_models.py | 19 +++++++++++++++++-- 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/django_tables/models.py b/django_tables/models.py index b0587e3..26d742e 100644 --- a/django_tables/models.py +++ b/django_tables/models.py @@ -96,6 +96,11 @@ class BaseModelTable(BaseTable): """Overridden. The snapshot in this case is simply a queryset with the necessary filters etc. attached. """ + + # reset caches + self._columns._reset() + self._rows = None + queryset = self.queryset if self.order_by: queryset = queryset.order_by(*self._cols_to_fields(self.order_by)) diff --git a/django_tables/tables.py b/django_tables/tables.py index da6c504..5216207 100644 --- a/django_tables/tables.py +++ b/django_tables/tables.py @@ -136,6 +136,11 @@ class BaseTable(object): In the case of this base table implementation, a copy of the source data is created, and then modified appropriately. """ + + # reset caches + self._columns._reset() + self._rows = None + snapshot = copy.copy(self._data) for row in snapshot: # delete unknown columns that are in the source data, but that @@ -239,6 +244,17 @@ class BaseTable(object): def as_html(self): pass + def update(self): + """Update the table based on it's current options. + + Normally, you won't have to call this method, since the table + updates itself (it's caches) automatically whenever you change + any of the properties. However, in some rare cases those + changes might not be picked up, for example if you manually + change ``base_columns`` or any of the columns in it. + """ + self._build_snapshot() + class Table(BaseTable): "A collection of columns, plus their associated data rows." # This is a separate class from BaseTable in order to abstract the way @@ -262,6 +278,10 @@ class Columns(object): self.table = table self._columns = SortedDict() + def _reset(self): + """Used by parent table class.""" + self._columns = SortedDict() + def _spawn_columns(self): # (re)build the "_columns" cache of BoundColumn objects (note that # ``base_columns`` might have changed since last time); creating diff --git a/tests/test_basic.py b/tests/test_basic.py index 086decc..e2f8d16 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -81,11 +81,6 @@ def test_basic(): books.base_columns['test'] = tables.Column() assert not 'test' in BookTable.base_columns - # make sure the row and column caches work - assert id(list(books.columns)[0]) == id(list(books.columns)[0]) - # TODO: row cache currently not used - #assert id(list(books.rows)[0]) == id(list(books.rows)[0]) - # optionally, exceptions can be raised when input is invalid tables.options.IGNORE_INVALID_OPTIONS = False raises(Exception, "books.order_by = '-name,made-up-column'") @@ -95,6 +90,28 @@ def test_basic(): # reset for future tests tables.options.IGNORE_INVALID_OPTIONS = True +def test_caches(): + """Ensure the various caches are effective. + """ + + class BookTable(tables.Table): + name = tables.Column() + answer = tables.Column(default=42) + books = BookTable([ + {'name': 'Foo: Bar'}, + ]) + + assert id(list(books.columns)[0]) == id(list(books.columns)[0]) + # TODO: row cache currently not used + #assert id(list(books.rows)[0]) == id(list(books.rows)[0]) + + # test that caches are reset after an update() + old_column_cache = id(list(books.columns)[0]) + old_row_cache = id(list(books.rows)[0]) + books.update() + assert id(list(books.columns)[0]) != old_column_cache + assert id(list(books.rows)[0]) != old_row_cache + def test_sort(): class BookTable(tables.Table): id = tables.Column() diff --git a/tests/test_models.py b/tests/test_models.py index 542d300..b2ca09c 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -125,11 +125,27 @@ def test_basic(): countries = CountryTable(Country) test_country_table(countries) - # make sure the row and column caches work for model tables as well +def test_caches(): + """Make sure the caches work for model tables as well (parts are + reimplemented). + """ + class CountryTable(tables.ModelTable): + class Meta: + model = Country + exclude = ('id',) + countries = CountryTable() + assert id(list(countries.columns)[0]) == id(list(countries.columns)[0]) # TODO: row cache currently not used #assert id(list(countries.rows)[0]) == id(list(countries.rows)[0]) + # test that caches are reset after an update() + old_column_cache = id(list(countries.columns)[0]) + old_row_cache = id(list(countries.rows)[0]) + countries.update() + assert id(list(countries.columns)[0]) != old_column_cache + assert id(list(countries.rows)[0]) != old_row_cache + def test_sort(): class CountryTable(tables.ModelTable): tld = tables.Column(name="domain") @@ -172,5 +188,4 @@ def test_pagination(): # TODO: pagination # TODO: support function column sources both for modeltables (methods on model) and static tables (functions in dict) -# TODO: manual base columns change -> update() call (add as example in docstr here) -> rebuild snapshot: is row cache, column cache etc. reset? # TODO: support relationship spanning columns (we could generate select_related() automatically) \ No newline at end of file -- 2.26.2